// 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 }
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 }
// 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 }