Skip to content

Commit dc1bbbb

Browse files
authored
HTTP inbound: Directly forward plain HTTP 1xx response header (#3434)
1 parent 6c93961 commit dc1bbbb

File tree

1 file changed

+34
-1
lines changed

1 file changed

+34
-1
lines changed

proxy/http/server.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package http
22

33
import (
44
"bufio"
5+
"bytes"
56
"context"
67
"encoding/base64"
78
"io"
@@ -275,7 +276,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
275276

276277
responseDone := func() error {
277278
responseReader := bufio.NewReaderSize(&buf.BufferedReader{Reader: link.Reader}, buf.Size)
278-
response, err := http.ReadResponse(responseReader, request)
279+
response, err := readResponseAndHandle100Continue(responseReader, request, writer)
279280
if err == nil {
280281
http_proto.RemoveHopByHopHeaders(response.Header)
281282
if response.ContentLength >= 0 {
@@ -319,6 +320,38 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
319320
return result
320321
}
321322

323+
// Sometimes, server might send 1xx response to client
324+
// it should not be processed by http proxy handler, just forward it to client
325+
func readResponseAndHandle100Continue(r *bufio.Reader, req *http.Request, writer io.Writer) (*http.Response, error) {
326+
// have a little look of response
327+
peekBytes, err := r.Peek(56)
328+
if err == nil || err == bufio.ErrBufferFull {
329+
str := string(peekBytes)
330+
ResponseLine := strings.Split(str, "\r\n")[0]
331+
_, status, _ := strings.Cut(ResponseLine, " ")
332+
// only handle 1xx response
333+
if strings.HasPrefix(status, "1") {
334+
ResponseHeader1xx := []byte{}
335+
// read until \r\n\r\n (end of http response header)
336+
for {
337+
data, err := r.ReadSlice('\n')
338+
if err != nil {
339+
return nil, newError("failed to read http 1xx response").Base(err).AtError()
340+
}
341+
ResponseHeader1xx = append(ResponseHeader1xx, data...)
342+
if bytes.Equal(ResponseHeader1xx[len(ResponseHeader1xx)-4:], []byte{'\r', '\n', '\r', '\n'}) {
343+
break
344+
}
345+
if len(ResponseHeader1xx) > 1024 {
346+
return nil, newError("too big http 1xx response").AtError()
347+
}
348+
}
349+
writer.Write(ResponseHeader1xx)
350+
}
351+
}
352+
return http.ReadResponse(r, req)
353+
}
354+
322355
func init() {
323356
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
324357
return NewServer(ctx, config.(*ServerConfig))

0 commit comments

Comments
 (0)