// This function alters the original request - adds/removes headers, removes hop headers,
// changes the request path.
func rewriteRequest(req *http.Request, cmd *command.Forward, upstream *command.Upstream) *http.Request {
	outReq := new(http.Request)
	*outReq = *req // includes shallow copies of maps, but we handle this below

	outReq.URL.Scheme = upstream.Scheme
	outReq.URL.Host = fmt.Sprintf("%s:%d", upstream.Host, upstream.Port)
	if len(cmd.RewritePath) != 0 {
		outReq.URL.Path = cmd.RewritePath
	}

	outReq.URL.RawQuery = req.URL.RawQuery

	outReq.Proto = "HTTP/1.1"
	outReq.ProtoMajor = 1
	outReq.ProtoMinor = 1
	outReq.Close = false

	glog.Infof("Proxying request to: %v", outReq)

	outReq.Header = make(http.Header)
	netutils.CopyHeaders(outReq.Header, req.Header)

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		// TODO(pquerna): configure this?  Not all backends properly parse the header..
		if TRUST_FORWARD_HEADER {
			if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
				clientIP = strings.Join(prior, ", ") + ", " + clientIP
			}
		}
		outReq.Header.Set("X-Forwarded-For", clientIP)
	}

	if req.TLS != nil {
		outReq.Header.Set("X-Forwarded-Proto", "https")
	} else {
		outReq.Header.Set("X-Forwarded-Proto", "http")
	}

	if req.Host != "" {
		outReq.Header.Set("X-Forwarded-Host", req.Host)
	}

	outReq.Header.Set("X-Forwarded-Server", vulcanHostname)

	if len(cmd.RemoveHeaders) != 0 {
		netutils.RemoveHeaders(cmd.RemoveHeaders, outReq.Header)
	}

	// Add generic instructions headers to the request
	if len(cmd.AddHeaders) != 0 {
		glog.Info("Proxying instructions headers:", cmd.AddHeaders)
		netutils.CopyHeaders(outReq.Header, cmd.AddHeaders)
	}

	// Remove hop-by-hop headers to the backend.  Especially
	// important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.
	netutils.RemoveHeaders(hopHeaders, outReq.Header)
	return outReq
}
func (rw *Rewriter) ProcessRequest(r Request) (*http.Response, error) {
	req := r.GetHttpRequest()

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		if rw.TrustForwardHeader {
			if prior, ok := req.Header[headers.XForwardedFor]; ok {
				clientIP = strings.Join(prior, ", ") + ", " + clientIP
			}
		}
		req.Header.Set(headers.XForwardedFor, clientIP)
	}

	if xfp := req.Header.Get(headers.XForwardedProto); xfp != "" && rw.TrustForwardHeader {
		req.Header.Set(headers.XForwardedProto, xfp)
	} else if req.TLS != nil {
		req.Header.Set(headers.XForwardedProto, "https")
	} else {
		req.Header.Set(headers.XForwardedProto, "http")
	}

	if req.Host != "" {
		req.Header.Set(headers.XForwardedHost, req.Host)
	}
	req.Header.Set(headers.XForwardedServer, rw.Hostname)

	// Remove hop-by-hop headers to the backend.  Especially important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.
	netutils.RemoveHeaders(headers.HopHeaders, req.Header)

	return nil, nil
}
Exemple #3
0
func (rw *Rewriter) ProcessRequest(r request.Request) (*http.Response, error) {
	req := r.GetHttpRequest()

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		if rw.TrustForwardHeader {
			if prior, ok := req.Header[headers.XForwardedFor]; ok {
				clientIP = strings.Join(prior, ", ") + ", " + clientIP
			}
		}
		req.Header.Set(headers.XForwardedFor, clientIP)
	}

	if xfp := req.Header.Get(headers.XForwardedProto); xfp != "" && rw.TrustForwardHeader {
		req.Header.Set(headers.XForwardedProto, xfp)
	} else if req.TLS != nil {
		req.Header.Set(headers.XForwardedProto, "https")
	} else {
		req.Header.Set(headers.XForwardedProto, "http")
	}

	if req.Host != "" {
		req.Header.Set(headers.XForwardedHost, req.Host)
	}
	req.Header.Set(headers.XForwardedServer, rw.Hostname)

	// Remove hop-by-hop headers to the backend.  Especially important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.
	netutils.RemoveHeaders(headers.HopHeaders, req.Header)

	// We need to set ContentLength based on known request size. The incoming request may have been
	// set without content length or using chunked TransferEncoding
	totalSize, err := r.GetBody().TotalSize()
	if err != nil {
		return nil, err
	}
	req.ContentLength = totalSize
	// Remove TransferEncoding that could have been previously set
	req.TransferEncoding = []string{}

	return nil, nil
}
Exemple #4
0
// This function alters the original request - adds/removes headers, removes hop headers, changes the request path.
func (l *HttpLocation) rewriteRequest(req *http.Request, endpoint Endpoint) *http.Request {
	outReq := new(http.Request)
	*outReq = *req // includes shallow copies of maps, but we handle this below

	outReq.URL.Scheme = endpoint.GetUrl().Scheme
	outReq.URL.Host = endpoint.GetUrl().Host
	outReq.URL.RawQuery = req.URL.RawQuery

	outReq.Proto = "HTTP/1.1"
	outReq.ProtoMajor = 1
	outReq.ProtoMinor = 1
	outReq.Close = false

	outReq.Header = make(http.Header)
	netutils.CopyHeaders(outReq.Header, req.Header)

	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		if l.options.TrustForwardHeader {
			if prior, ok := outReq.Header[headers.XForwardedFor]; ok {
				clientIP = strings.Join(prior, ", ") + ", " + clientIP
			}
		}
		outReq.Header.Set(headers.XForwardedFor, clientIP)
	}
	if req.TLS != nil {
		outReq.Header.Set(headers.XForwardedProto, "https")
	} else {
		outReq.Header.Set(headers.XForwardedProto, "http")
	}
	if req.Host != "" {
		outReq.Header.Set(headers.XForwardedHost, req.Host)
	}
	outReq.Header.Set(headers.XForwardedServer, l.options.Hostname)

	// Remove hop-by-hop headers to the backend.  Especially important is "Connection" because we want a persistent
	// connection, regardless of what the client sent to us.
	netutils.RemoveHeaders(headers.HopHeaders, outReq.Header)
	return outReq
}