Browse Source

Transform hop-by-hop headers (using logic from httputil.ReverseProxy)

Rod Hynes 11 years ago
parent
commit
60701ca819
1 changed files with 27 additions and 15 deletions
  1. 27 15
      psiphon/httpProxy.go

+ 27 - 15
psiphon/httpProxy.go

@@ -25,9 +25,7 @@ import (
 	"log"
 	"net"
 	"net/http"
-	"strings"
 	"sync"
-	"unicode"
 )
 
 // HttpProxy is a HTTP server that relays HTTP requests through
@@ -84,6 +82,11 @@ func (proxy *HttpProxy) Close() {
 // Copyright (c) 2014 JianjunMao
 // The MIT License (MIT)
 //
+// https://golang.org/src/pkg/net/http/httputil/reverseproxy.go
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+//
 func (proxy *HttpProxy) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
 	if request.Method == "CONNECT" {
 		hijacker, _ := responseWriter.(http.Hijacker)
@@ -106,19 +109,12 @@ func (proxy *HttpProxy) ServeHTTP(responseWriter http.ResponseWriter, request *h
 		http.Error(responseWriter, "", http.StatusInternalServerError)
 		return
 	}
-	// Transform request struct before using as input to relayed request:
-	// Scheme: must be lower case.
-	// RequestURI: cleared as docs state "It is an error to set this
-	// field in an HTTP client request".
-	// Accept-Encoding: removed to allow Go's RoundTripper to do its own
-	// encoding.
-	// Connection (and the bogus Proxy-Connection): inputs to the proxy
-	// only and not to be passed along.
-	request.URL.Scheme = strings.Map(unicode.ToLower, request.URL.Scheme)
+	// Transform request struct before using as input to relayed request
+	request.Close = false
 	request.RequestURI = ""
-	request.Header.Del("Accept-Encoding")
-	request.Header.Del("Proxy-Connection")
-	request.Header.Del("Connection")
+	for _, key := range hopHeaders {
+		request.Header.Del(key)
+	}
 	// Relay the HTTP request and get the response
 	response, err := proxy.httpRelay.RoundTrip(request)
 	if err != nil {
@@ -127,7 +123,10 @@ func (proxy *HttpProxy) ServeHTTP(responseWriter http.ResponseWriter, request *h
 		return
 	}
 	defer response.Body.Close()
-	// Relay the remote response headers (first removing any proxy server headers)
+	// Relay the remote response headers
+	for _, key := range hopHeaders {
+		response.Header.Del(key)
+	}
 	for key, _ := range responseWriter.Header() {
 		responseWriter.Header().Del(key)
 	}
@@ -146,6 +145,19 @@ func (proxy *HttpProxy) ServeHTTP(responseWriter http.ResponseWriter, request *h
 	}
 }
 
+// Hop-by-hop headers. These are removed when sent to the backend.
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
+var hopHeaders = []string{
+	"Connection",
+	"Keep-Alive",
+	"Proxy-Authenticate",
+	"Proxy-Authorization",
+	"Te", // canonicalized version of "TE"
+	"Trailers",
+	"Transfer-Encoding",
+	"Upgrade",
+}
+
 func httpConnectHandler(tunnel *Tunnel, localHttpConn net.Conn, target string) (err error) {
 	defer localHttpConn.Close()
 	remoteSshForward, err := tunnel.sshClient.Dial("tcp", target)