This commit is contained in:
fhgffy 2026-10-13 11:38:41 -05:00 committed by GitHub
commit 8c4502b3e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 102 additions and 1 deletions

View File

@ -72,6 +72,9 @@ func parseStartLine(line string) (r1, r2, r3 string, ok bool) {
} }
func cleanHeaders(header textproto.MIMEHeader) { func cleanHeaders(header textproto.MIMEHeader) {
if len(header.Values("Transfer-Encoding")) > 0 {
header.Del("Content-Length")
}
header.Del("Proxy-Connection") header.Del("Proxy-Connection")
header.Del("Connection") header.Del("Connection")
header.Del("Keep-Alive") header.Del("Keep-Alive")
@ -79,7 +82,6 @@ func cleanHeaders(header textproto.MIMEHeader) {
header.Del("Proxy-Authorization") header.Del("Proxy-Authorization")
header.Del("TE") header.Del("TE")
header.Del("Trailers") header.Del("Trailers")
header.Del("Transfer-Encoding")
header.Del("Upgrade") header.Del("Upgrade")
} }

99
proxy/http/server_test.go Normal file
View File

@ -0,0 +1,99 @@
package http
import (
"bufio"
"bytes"
"io"
"net"
stdhttp "net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/nadoo/glider/proxy"
)
type directTestProxy struct{}
func (directTestProxy) Addr() string { return "direct" }
func (p directTestProxy) Dial(network, addr string) (net.Conn, proxy.Dialer, error) {
c, err := net.Dial(network, addr)
return c, &proxy.Direct{}, err
}
func (directTestProxy) DialUDP(string, string) (net.PacketConn, proxy.UDPDialer, error) {
return nil, &proxy.Direct{}, proxy.ErrNotSupported
}
func (directTestProxy) NextDialer(string) proxy.Dialer { return &proxy.Direct{} }
func (directTestProxy) Record(proxy.Dialer, bool) {}
func TestServeForwardsChunkedRequestBody(t *testing.T) {
origin := httptest.NewServer(stdhttp.HandlerFunc(func(w stdhttp.ResponseWriter, r *stdhttp.Request) {
body, err := io.ReadAll(r.Body)
if err != nil {
stdhttp.Error(w, err.Error(), stdhttp.StatusBadRequest)
return
}
w.Write(body)
}))
defer origin.Close()
client, server := net.Pipe()
defer client.Close()
client.SetDeadline(time.Now().Add(3 * time.Second))
done := make(chan struct{})
go func() {
defer close(done)
s := &HTTP{proxy: directTestProxy{}}
s.Serve(server)
}()
request := "POST " + origin.URL + "/upload HTTP/1.1\r\n" +
"Host: " + strings.TrimPrefix(origin.URL, "http://") + "\r\n" +
"Transfer-Encoding: chunked\r\nConnection: close\r\n\r\n" +
"5\r\nhello\r\n6\r\n world\r\n0\r\n\r\n"
if _, err := io.WriteString(client, request); err != nil {
t.Fatal(err)
}
response, err := stdhttp.ReadResponse(bufio.NewReader(client), nil)
if err != nil {
t.Fatal(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
t.Fatal(err)
}
if response.StatusCode != stdhttp.StatusOK || string(body) != "hello world" {
t.Fatalf("upstream response = %d %q, want 200 hello world", response.StatusCode, body)
}
client.Close()
<-done
}
func TestRequestFramingHeaders(t *testing.T) {
for _, tt := range []struct {
name string
headers string
transferCoding bool
contentLength bool
}{
{"chunked", "Transfer-Encoding: chunked\r\n", true, false},
{"chunked with length", "Transfer-Encoding: chunked\r\nContent-Length: 1\r\n", true, false},
{"content length", "Content-Length: 11\r\n", false, true},
} {
t.Run(tt.name, func(t *testing.T) {
raw := "POST http://example.com/upload HTTP/1.1\r\nHost: example.com\r\n" + tt.headers + "\r\n"
req, err := parseRequest(bufio.NewReader(strings.NewReader(raw)))
if err != nil {
t.Fatal(err)
}
var wire bytes.Buffer
req.WriteBuf(&wire)
if got := strings.Contains(wire.String(), "Transfer-Encoding:"); got != tt.transferCoding {
t.Errorf("Transfer-Encoding present = %v, want %v", got, tt.transferCoding)
}
if got := strings.Contains(wire.String(), "Content-Length:"); got != tt.contentLength {
t.Errorf("Content-Length present = %v, want %v", got, tt.contentLength)
}
})
}
}