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"
|
||||
"github.com/go-gost/core/observer/stats"
|
||||
ctxvalue "github.com/go-gost/x/ctx"
|
||||
xio "github.com/go-gost/x/internal/io"
|
||||
netpkg "github.com/go-gost/x/internal/net"
|
||||
stats_util "github.com/go-gost/x/internal/util/stats"
|
||||
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 {
|
||||
return h.handleProxy(rw, cc, req, log)
|
||||
return h.handleProxy(xio.NewReadWriteCloser(rw, rw, conn), cc, req, log)
|
||||
}
|
||||
|
||||
resp.StatusCode = http.StatusOK
|
||||
@ -261,25 +262,78 @@ func (h *httpHandler) handleRequest(ctx context.Context, conn net.Conn, req *htt
|
||||
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")
|
||||
|
||||
if err = req.Write(cc); err != nil {
|
||||
log.Error(err)
|
||||
resp.Write(rw)
|
||||
return err
|
||||
}
|
||||
|
||||
ch := make(chan error, 1)
|
||||
|
||||
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 {
|
||||
err := func() error {
|
||||
req, err := http.ReadRequest(bufio.NewReader(rw))
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
@ -290,23 +344,12 @@ func (h *httpHandler) handleProxy(rw, cc io.ReadWriter, req *http.Request, log l
|
||||
log.Trace(string(dump))
|
||||
}
|
||||
|
||||
req.Header.Del("Proxy-Connection")
|
||||
|
||||
if err = req.Write(cc); err != nil {
|
||||
if err = roundTrip(req); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
ch <- err
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return <-ch
|
||||
}
|
||||
|
||||
func (h *httpHandler) decodeServerName(s string) (string, error) {
|
||||
b, err := base64.RawURLEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user