From 1f226797bc955444b354621a836e8c7915b99b73 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Mon, 18 Dec 2017 20:59:43 +0100 Subject: [PATCH] remove header operation to http protocol package --- common/protocol/http/headers.go | 23 +++++++++++++ common/protocol/http/headers_test.go | 35 ++++++++++++++++++++ proxy/http/server.go | 39 +++++----------------- proxy/http/server_test.go | 48 ---------------------------- 4 files changed, 66 insertions(+), 79 deletions(-) delete mode 100644 proxy/http/server_test.go diff --git a/common/protocol/http/headers.go b/common/protocol/http/headers.go index c5c0644a..7c81274e 100644 --- a/common/protocol/http/headers.go +++ b/common/protocol/http/headers.go @@ -19,3 +19,26 @@ func ParseXForwardedFor(header http.Header) []net.Address { } return addrs } + +func RemoveHopByHopHeaders(header http.Header) { + // Strip hop-by-hop header based on RFC: + // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 + // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do + + header.Del("Proxy-Connection") + header.Del("Proxy-Authenticate") + header.Del("Proxy-Authorization") + header.Del("TE") + header.Del("Trailers") + header.Del("Transfer-Encoding") + header.Del("Upgrade") + + connections := header.Get("Connection") + header.Del("Connection") + if len(connections) == 0 { + return + } + for _, h := range strings.Split(connections, ",") { + header.Del(strings.TrimSpace(h)) + } +} diff --git a/common/protocol/http/headers_test.go b/common/protocol/http/headers_test.go index f1119a67..76edfd38 100644 --- a/common/protocol/http/headers_test.go +++ b/common/protocol/http/headers_test.go @@ -1,7 +1,9 @@ package http_test import ( + "bufio" "net/http" + "strings" "testing" . "v2ray.com/core/common/protocol/http" @@ -18,3 +20,36 @@ func TestParseXForwardedFor(t *testing.T) { assert(addrs[0].String(), Equals, "129.78.138.66") assert(addrs[1].String(), Equals, "129.78.64.103") } + +func TestHopByHopHeadersRemoving(t *testing.T) { + assert := With(t) + + rawRequest := `GET /pkg/net/http/ HTTP/1.1 +Host: golang.org +Connection: keep-alive,Foo, Bar +Foo: foo +Bar: bar +Proxy-Connection: keep-alive +Proxy-Authenticate: abc +Accept-Encoding: gzip +Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7 +Cache-Control: no-cache +Accept-Language: de,en;q=0.7,en-us;q=0.3 + +` + b := bufio.NewReader(strings.NewReader(rawRequest)) + req, err := http.ReadRequest(b) + assert(err, IsNil) + assert(req.Header.Get("Foo"), Equals, "foo") + assert(req.Header.Get("Bar"), Equals, "bar") + assert(req.Header.Get("Connection"), Equals, "keep-alive,Foo, Bar") + assert(req.Header.Get("Proxy-Connection"), Equals, "keep-alive") + assert(req.Header.Get("Proxy-Authenticate"), Equals, "abc") + + RemoveHopByHopHeaders(req.Header) + assert(req.Header.Get("Connection"), IsEmpty) + assert(req.Header.Get("Foo"), IsEmpty) + assert(req.Header.Get("Bar"), IsEmpty) + assert(req.Header.Get("Proxy-Connection"), IsEmpty) + assert(req.Header.Get("Proxy-Authenticate"), IsEmpty) +} diff --git a/proxy/http/server.go b/proxy/http/server.go index fa2f9e50..0ee100e5 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -18,6 +18,7 @@ import ( "v2ray.com/core/common/buf" "v2ray.com/core/common/errors" "v2ray.com/core/common/net" + http_proto "v2ray.com/core/common/protocol/http" "v2ray.com/core/common/signal" "v2ray.com/core/transport/internet" ) @@ -210,35 +211,6 @@ func (s *Server) handleConnect(ctx context.Context, request *http.Request, reade return nil } -// @VisibleForTesting -func StripHopByHopHeaders(header http.Header) { - // Strip hop-by-hop header basaed on RFC: - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 - // https://www.mnot.net/blog/2011/07/11/what_proxies_must_do - - header.Del("Proxy-Connection") - header.Del("Proxy-Authenticate") - header.Del("Proxy-Authorization") - header.Del("TE") - header.Del("Trailers") - header.Del("Transfer-Encoding") - header.Del("Upgrade") - - connections := header.Get("Connection") - header.Del("Connection") - if len(connections) == 0 { - return - } - for _, h := range strings.Split(connections, ",") { - header.Del(strings.TrimSpace(h)) - } - - // Prevent UA from being set to golang's default ones - if len(header.Get("User-Agent")) == 0 { - header.Set("User-Agent", "") - } -} - var errWaitAnother = newError("keep alive") func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, writer io.Writer, dest net.Destination, dispatcher dispatcher.Interface) error { @@ -263,7 +235,12 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri if len(request.URL.Host) > 0 { request.Host = request.URL.Host } - StripHopByHopHeaders(request.Header) + http_proto.RemoveHopByHopHeaders(request.Header) + + // Prevent UA from being set to golang's default ones + if len(request.Header.Get("User-Agent")) == 0 { + request.Header.Set("User-Agent", "") + } ray, err := dispatcher.Dispatch(ctx, dest) if err != nil { @@ -290,7 +267,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri responseReader := bufio.NewReaderSize(buf.NewBufferedReader(ray.InboundOutput()), buf.Size) response, err := http.ReadResponse(responseReader, request) if err == nil { - StripHopByHopHeaders(response.Header) + http_proto.RemoveHopByHopHeaders(response.Header) if response.ContentLength >= 0 { response.Header.Set("Proxy-Connection", "keep-alive") response.Header.Set("Connection", "keep-alive") diff --git a/proxy/http/server_test.go b/proxy/http/server_test.go deleted file mode 100644 index c4b156f1..00000000 --- a/proxy/http/server_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package http_test - -import ( - "bufio" - "net/http" - "strings" - "testing" - - . "v2ray.com/core/proxy/http" - . "v2ray.com/ext/assert" - - _ "v2ray.com/core/transport/internet/tcp" -) - -func TestHopByHopHeadersStrip(t *testing.T) { - assert := With(t) - - rawRequest := `GET /pkg/net/http/ HTTP/1.1 -Host: golang.org -Connection: keep-alive,Foo, Bar -Foo: foo -Bar: bar -Proxy-Connection: keep-alive -Proxy-Authenticate: abc -Accept-Encoding: gzip -Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7 -Cache-Control: no-cache -Accept-Language: de,en;q=0.7,en-us;q=0.3 - -` - b := bufio.NewReader(strings.NewReader(rawRequest)) - req, err := http.ReadRequest(b) - assert(err, IsNil) - assert(req.Header.Get("Foo"), Equals, "foo") - assert(req.Header.Get("Bar"), Equals, "bar") - assert(req.Header.Get("Connection"), Equals, "keep-alive,Foo, Bar") - assert(req.Header.Get("Proxy-Connection"), Equals, "keep-alive") - assert(req.Header.Get("Proxy-Authenticate"), Equals, "abc") - assert(req.Header.Get("User-Agent"), IsEmpty) - - StripHopByHopHeaders(req.Header) - assert(req.Header.Get("Connection"), IsEmpty) - assert(req.Header.Get("Foo"), IsEmpty) - assert(req.Header.Get("Bar"), IsEmpty) - assert(req.Header.Get("Proxy-Connection"), IsEmpty) - assert(req.Header.Get("Proxy-Authenticate"), IsEmpty) - assert(req.Header.Get("User-Agent"), IsEmpty) -}