mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2024-12-26 20:26:06 +08:00
96 lines
1.8 KiB
Go
96 lines
1.8 KiB
Go
|
package mitm
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"compress/gzip"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
"time"
|
||
|
|
||
|
"golang.org/x/text/encoding/charmap"
|
||
|
"golang.org/x/text/transform"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
ErrInvalidResponse = errors.New("invalid response")
|
||
|
ErrInvalidURL = errors.New("invalid URL")
|
||
|
)
|
||
|
|
||
|
func NewResponse(code int, body io.Reader, req *http.Request) *http.Response {
|
||
|
if body == nil {
|
||
|
body = &bytes.Buffer{}
|
||
|
}
|
||
|
|
||
|
rc, ok := body.(io.ReadCloser)
|
||
|
if !ok {
|
||
|
rc = ioutil.NopCloser(body)
|
||
|
}
|
||
|
|
||
|
res := &http.Response{
|
||
|
StatusCode: code,
|
||
|
Status: fmt.Sprintf("%d %s", code, http.StatusText(code)),
|
||
|
Proto: "HTTP/1.1",
|
||
|
ProtoMajor: 1,
|
||
|
ProtoMinor: 1,
|
||
|
Header: http.Header{},
|
||
|
Body: rc,
|
||
|
Request: req,
|
||
|
}
|
||
|
|
||
|
if req != nil {
|
||
|
res.Close = req.Close
|
||
|
res.Proto = req.Proto
|
||
|
res.ProtoMajor = req.ProtoMajor
|
||
|
res.ProtoMinor = req.ProtoMinor
|
||
|
}
|
||
|
|
||
|
return res
|
||
|
}
|
||
|
|
||
|
func NewErrorResponse(req *http.Request, err error) *http.Response {
|
||
|
res := NewResponse(http.StatusBadGateway, nil, req)
|
||
|
res.Close = true
|
||
|
|
||
|
date := res.Header.Get("Date")
|
||
|
if date == "" {
|
||
|
date = time.Now().Format(http.TimeFormat)
|
||
|
}
|
||
|
|
||
|
w := fmt.Sprintf(`199 "clash" %q %q`, err.Error(), date)
|
||
|
res.Header.Add("Warning", w)
|
||
|
return res
|
||
|
}
|
||
|
|
||
|
func ReadDecompressedBody(res *http.Response) ([]byte, error) {
|
||
|
rBody := res.Body
|
||
|
if res.Header.Get("Content-Encoding") == "gzip" {
|
||
|
gzReader, err := gzip.NewReader(rBody)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
rBody = gzReader
|
||
|
|
||
|
defer func(gzReader *gzip.Reader) {
|
||
|
_ = gzReader.Close()
|
||
|
}(gzReader)
|
||
|
}
|
||
|
return ioutil.ReadAll(rBody)
|
||
|
}
|
||
|
|
||
|
func DecodeLatin1(reader io.Reader) (string, error) {
|
||
|
r := transform.NewReader(reader, charmap.ISO8859_1.NewDecoder())
|
||
|
b, err := ioutil.ReadAll(r)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return string(b), nil
|
||
|
}
|
||
|
|
||
|
func EncodeLatin1(str string) ([]byte, error) {
|
||
|
return charmap.ISO8859_1.NewEncoder().Bytes([]byte(str))
|
||
|
}
|