compatible with HTTP/1.0
This commit is contained in:
parent
1a776dc759
commit
5e8a8a4b4d
@ -24,6 +24,7 @@ import (
|
|||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
"github.com/go-gost/core/observer/stats"
|
"github.com/go-gost/core/observer/stats"
|
||||||
ctxvalue "github.com/go-gost/x/ctx"
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
|
xio "github.com/go-gost/x/internal/io"
|
||||||
netpkg "github.com/go-gost/x/internal/net"
|
netpkg "github.com/go-gost/x/internal/net"
|
||||||
stats_util "github.com/go-gost/x/internal/util/stats"
|
stats_util "github.com/go-gost/x/internal/util/stats"
|
||||||
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
traffic_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
@ -236,7 +237,7 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.Method != http.MethodConnect {
|
if req.Method != http.MethodConnect {
|
||||||
return h.handleProxy(rw, cc, req, log)
|
return h.handleProxy(xio.NewReadWriteCloser(rw, rw, conn), cc, req, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.StatusCode = http.StatusOK
|
resp.StatusCode = http.StatusOK
|
||||||
@ -261,25 +262,78 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *httpHandler) handleProxy(rw, cc io.ReadWriter, req *http.Request, log logger.Logger) (err error) {
|
func (h *httpHandler) handleProxy(rw io.ReadWriteCloser, cc io.ReadWriter, req *http.Request, log logger.Logger) (err error) {
|
||||||
|
roundTrip := func(req *http.Request) error {
|
||||||
|
if req == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &http.Response{
|
||||||
|
ProtoMajor: req.ProtoMajor,
|
||||||
|
ProtoMinor: req.ProtoMinor,
|
||||||
|
Header: http.Header{},
|
||||||
|
StatusCode: http.StatusServiceUnavailable,
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP/1.0
|
||||||
|
if req.ProtoMajor == 1 && req.ProtoMinor == 0 {
|
||||||
|
if strings.ToLower(req.Header.Get("Connection")) == "keep-alive" {
|
||||||
|
req.Header.Del("Connection")
|
||||||
|
} else {
|
||||||
|
req.Header.Set("Connection", "close")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req.Header.Del("Proxy-Connection")
|
req.Header.Del("Proxy-Connection")
|
||||||
|
|
||||||
if err = req.Write(cc); err != nil {
|
if err = req.Write(cc); err != nil {
|
||||||
log.Error(err)
|
resp.Write(rw)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan error, 1)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
ch <- netpkg.CopyBuffer(rw, cc, 32*1024)
|
res, err := http.ReadResponse(bufio.NewReader(cc), req)
|
||||||
|
if err != nil {
|
||||||
|
h.options.Logger.Errorf("read response: %v", err)
|
||||||
|
resp.Write(rw)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if log.IsLevelEnabled(logger.TraceLevel) {
|
||||||
|
dump, _ := httputil.DumpResponse(res, false)
|
||||||
|
log.Trace(string(dump))
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Close {
|
||||||
|
defer rw.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP/1.0
|
||||||
|
if req.ProtoMajor == 1 && req.ProtoMinor == 0 {
|
||||||
|
if !res.Close {
|
||||||
|
res.Header.Set("Connection", "keep-alive")
|
||||||
|
}
|
||||||
|
res.ProtoMajor = req.ProtoMajor
|
||||||
|
res.ProtoMinor = req.ProtoMinor
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = res.Write(rw); err != nil {
|
||||||
|
rw.Close()
|
||||||
|
log.Errorf("write response: %v", err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = roundTrip(req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
err := func() error {
|
|
||||||
req, err := http.ReadRequest(bufio.NewReader(rw))
|
req, err := http.ReadRequest(bufio.NewReader(rw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == io.EOF {
|
if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -290,23 +344,12 @@ func (h *httpHandler) handleProxy(rw, cc io.ReadWriter, req *http.Request, log l
|
|||||||
log.Trace(string(dump))
|
log.Trace(string(dump))
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Del("Proxy-Connection")
|
if err = roundTrip(req); err != nil {
|
||||||
|
|
||||||
if err = req.Write(cc); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}()
|
|
||||||
ch <- err
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <-ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *httpHandler) decodeServerName(s string) (string, error) {
|
func (h *httpHandler) decodeServerName(s string) (string, error) {
|
||||||
b, err := base64.RawURLEncoding.DecodeString(s)
|
b, err := base64.RawURLEncoding.DecodeString(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user