func (rw *rewriteHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { oldURL := rawURL(req) // apply a rewrite regexp to the URL newURL := rw.regexp.ReplaceAllString(oldURL, rw.replacement) // replace any variables that may be in there rewrittenURL := &bytes.Buffer{} if err := ApplyString(newURL, rewrittenURL, req); err != nil { rw.errHandler.ServeHTTP(w, req, err) return } // parse the rewritten URL and replace request URL with it parsedURL, err := url.Parse(rewrittenURL.String()) if err != nil { rw.errHandler.ServeHTTP(w, req, err) return } if rw.redirect && newURL != oldURL { (&redirectHandler{u: parsedURL}).ServeHTTP(w, req) return } req.URL = parsedURL // make sure the request URI corresponds the rewritten URL req.RequestURI = req.URL.Path if req.URL.RawQuery != "" { req.RequestURI = strings.Join([]string{req.RequestURI, "?", req.URL.RawQuery}, "") } if !rw.rewriteBody { rw.next.ServeHTTP(w, req) return } bw := &bufferWriter{header: make(http.Header), buffer: &bytes.Buffer{}} newBody := &bytes.Buffer{} rw.next.ServeHTTP(bw, req) if err := Apply(bw.buffer, newBody, req); err != nil { log.Errorf("Failed to rewrite response body: %v", err) return } utils.CopyHeaders(w.Header(), bw.Header()) w.Header().Set("Content-Length", strconv.Itoa(newBody.Len())) w.WriteHeader(bw.code) io.Copy(w, newBody) }
func proxyRequest(w http.ResponseWriter, r *http.Request, backendAddress string) { r.RequestURI = "" if r.Header["Connection"] != nil && r.Header["Connection"][0] == "Upgrade" && r.Header["Upgrade"] != nil && r.Header["Upgrade"][0] == "websocket" { proxyWebsocket(w, r, backendAddress) return } r.URL.Scheme = "http" r.URL.Host = backendAddress resp, err := http.DefaultTransport.RoundTrip(r) if err != nil { writeErrorPage(w, err) return } writeResponseHeader(w, resp) // just stream the body to the client _, err = io.Copy(w, resp.Body) if err != nil { log.Println(err) } }
func handler(w http.ResponseWriter, r *http.Request) { log.Println("----------------------------------") log.Println("RequestURI", r.RequestURI) log.Println("RemoteAddr", r.RemoteAddr) //log.Println("URL", r.URL) log.Println("----------------------------------") //http: Request.RequestURI can't be set in client requests. //http://golang.org/src/pkg/net/http/client.go r.RequestURI = "" //log.Println("RequestURI", r.RequestURI) resp, err := http.DefaultClient.Do(r) defer resp.Body.Close() if err != nil { panic(err) } for k, v := range resp.Header { for _, vv := range v { w.Header().Add(k, vv) } } w.WriteHeader(resp.StatusCode) result, err := ioutil.ReadAll(resp.Body) if err != nil && err != io.EOF { panic(err) } w.Write(result) }
func serveHTTP(w http.ResponseWriter, r *http.Request) { defer logreq(r, time.Now()) if r.Method == "CONNECT" { err := connect(w, r) if err != nil { log.Printf("%s", err) } return } r.RequestURI = "" for _, h := range hopHeaders { if r.Header.Get(h) != "" { r.Header.Del(h) } } resp, err := trans.RoundTrip(r) if err != nil { log.Printf("%s", err) w.WriteHeader(http.StatusInternalServerError) return } defer resp.Body.Close() copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) _, err = io.Copy(w, resp.Body) if err != nil { log.Printf("copy error:%s", err) } }
// doRequest performs original request and returns response that should be returned to client and error (if there is one) func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) { // We can't have this set. And it only contains "/pkg/net/http/" anyway request.RequestURI = "" resp, err := d.http.Do(request) if err != nil { log.WithFields(log.Fields{ "error": err.Error(), "host": request.Host, "method": request.Method, "path": request.URL.Path, }).Error("Could not forward request.") return nil, err } log.WithFields(log.Fields{ "host": request.Host, "method": request.Method, "path": request.URL.Path, }).Info("Response got successfuly!") resp.Header.Set("Gen-proxy", "Was-Here") return resp, nil }
func (f *Forwarder) copyRequest(req *http.Request, u *url.URL) *http.Request { outReq := new(http.Request) *outReq = *req // includes shallow copies of maps, but we handle this below outReq.URL = utils.CopyURL(req.URL) outReq.RequestURI = "" outReq.URL.Scheme = u.Scheme outReq.URL.Host = u.Host outReq.URL.Opaque = req.RequestURI // raw query is already included in RequestURI, so ignore it to avoid dupes outReq.URL.RawQuery = "" // Do not pass client Host header unless optsetter PassHostHeader is set. if f.passHost != true { outReq.Host = u.Host } outReq.Proto = "HTTP/1.1" outReq.ProtoMajor = 1 outReq.ProtoMinor = 1 // Overwrite close flag so we can keep persistent connection for the backend servers outReq.Close = false outReq.Header = make(http.Header) utils.CopyHeaders(outReq.Header, req.Header) if f.rewriter != nil { f.rewriter.Rewrite(outReq) } return outReq }
//a normally server proxy func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { //TODO you can do something what limit the user's request seis := strings.Split(r.Header.Get("Proxy-Authenticate"), ";") if seis[len(seis)-1] != s.psw { http.Error(w, "error", 407) return } r.Header.Del("Proxy-Authenticate") if r.Method == "CONNECT" { handleHttps(w, r) return } r.RequestURI = "" //TODO remove the unuse head resp, err := transport.RoundTrip(r) if err != nil { //TODO write the error to the log file println(err.Error()) return } defer resp.Body.Close() copyHeaders(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) }
func handleHttp(rw http.ResponseWriter, req *http.Request) { log.Printf("host: %s, scheme: %s, path: %s, url.Host: %s", req.Host, req.URL.Scheme, req.URL.Path, req.URL.Host) req.RequestURI = "" res, err := httpClient.Do(req) if err != nil { log.Printf("http: proxy error: %v", err) rw.WriteHeader(http.StatusInternalServerError) return } defer res.Body.Close() header := rw.Header() for k, vv := range res.Header { for _, v := range vv { header.Add(k, v) } } rw.WriteHeader(res.StatusCode) if res.Body != nil { io.Copy(rw, res.Body) } }
func proxyAsync(tlsConfig *tls.Config, addr string, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error { // Use a new client for each request client, scheme := newClientAndScheme(tlsConfig) // RequestURI may not be sent to client r.RequestURI = "" r.URL.Scheme = scheme r.URL.Host = addr log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Debug("Proxy request") resp, err := client.Do(r) if err != nil { return err } copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(NewWriteFlusher(w), resp.Body) if callback != nil { callback(resp) } // cleanup resp.Body.Close() closeIdleConnections(client) return nil }
func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // output request request, err := httputil.DumpRequest(r, false) if err != nil { fmt.Println(err) } fmt.Println(string(request)) // create client to get site tr := &http.Transport{} //client := http.Client{} r.RequestURI = "" // pay attention : it is very important //response, err := client.Do(r) response, err := tr.RoundTrip(r) if err != nil { log.Panic(err, "not get response") } defer response.Body.Close() data, err := ioutil.ReadAll(response.Body) if err != nil { log.Panic(err, "not get Body") } fmt.Println("Get Body") // save Header for i, j := range response.Header { for _, k := range j { w.Header().Add(i, k) } } w.WriteHeader(response.StatusCode) w.Write(data) }
// TODO - refactor this function to use context // TODO - add support for SSL func (handler *Handler) proxy(w http.ResponseWriter, r *http.Request) { r.URL.Host = handler.Flywheel.ProxyEndpoint(r.Host) r.URL.Scheme = "http" r.RequestURI = "" r.URL.Query().Del("flywheel") resp, err := handler.HTTPClient.Do(r) if err != nil { if urlError, ok := err.(*url.Error); ok && urlError.Err == ErrIgnoreRedirects { err = nil } else { log.Print(err) w.WriteHeader(http.StatusServiceUnavailable) return } } for key, value := range resp.Header { w.Header()[key] = value } w.WriteHeader(resp.StatusCode) _, err = io.Copy(w, resp.Body) // if response code is between 300 and 400 sometimes body does not exist if err != nil && (!(resp.StatusCode >= 300 && resp.StatusCode < 400)) { log.Print(err) } }
// NewFastHTTPHandler wraps net/http handler to fasthttp request handler, // so it can be passed to fasthttp server. // // While this function may be used for easy switching from net/http to fasthttp, // it has the following drawbacks comparing to using manually written fasthttp // request handler: // // * A lot of useful functionality provided by fasthttp is missing // from net/http handler. // * net/http -> fasthttp handler conversion has some overhead, // so the returned handler will be always slower than manually written // fasthttp handler. // // So it is advisable using this function only for quick net/http -> fasthttp // switching. Then manually convert net/http handlers to fasthttp handlers // according to https://github.com/valyala/fasthttp#switching-from-nethttp-to-fasthttp . func NewFastHTTPHandler(h http.Handler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { var r http.Request body := ctx.PostBody() r.Method = string(ctx.Method()) r.Proto = "HTTP/1.1" r.ProtoMajor = 1 r.ProtoMinor = 1 r.RequestURI = string(ctx.RequestURI()) r.ContentLength = int64(len(body)) r.Host = string(ctx.Host()) r.RemoteAddr = ctx.RemoteAddr().String() hdr := make(http.Header) ctx.Request.Header.VisitAll(func(k, v []byte) { hdr.Set(string(k), string(v)) }) r.Header = hdr r.Body = &netHTTPBody{body} var w netHTTPResponseWriter h.ServeHTTP(&w, &r) ctx.SetStatusCode(w.StatusCode()) for k, vv := range w.Header() { for _, v := range vv { ctx.Response.Header.Set(k, v) } } ctx.Write(w.body) } }
// ServeHTTP handles the response func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { if ProxyPath != "" && strings.HasPrefix(req.URL.Path, "/"+ProxyPath) { uri, err := url.Parse(req.FormValue("uri")) if err != nil { s.debug.Println(req.RequestURI, err.Error()) } req.URL = uri req.Host = uri.Host req.RequestURI = uri.RequestURI() proxy.ServeHTTP(w, req) return } if websocketUpgrade(req) { websocketServe(w, req) return } defer func() { req.Body.Close() }() r := s.handle(w, &httpRequest{req, s}) for key := range r.headers { w.Header().Set(key, r.headers.Get(key)) } if r.status > 0 { w.WriteHeader(r.status) } if len(r.argv) > 0 { fmt.Fprint(w, r.argv...) } }
// HTTP proxy accepts requests with following two types: // - CONNECT // Generally, this method is used when the client want to connect server with HTTPS. // In fact, the client can do anything he want in this CONNECT way... // The request is something like: // CONNECT www.google.com:443 HTTP/1.1 // Only has the host and port information, and the proxy should not do anything with // the underlying data. What the proxy can do is just exchange data between client and server. // After accepting this, the proxy should response // HTTP/1.1 200 OK // to the client if the connection to the remote server is established. // Then client and server start to exchange data... // // - non-CONNECT, such as GET, POST, ... // In this case, the proxy should redo the method to the remote server. // All of these methods should have the absolute URL that contains the host information. // A GET request looks like: // GET weibo.com/justmao945/.... HTTP/1.1 // which is different from the normal http request: // GET /justmao945/... HTTP/1.1 // Because we can be sure that all of them are http request, we can only redo the request // to the remote server and copy the reponse to client. // func (self *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { L.Printf("%s %s %s\n", r.Method, r.RequestURI, r.Proto) if r.Method == "CONNECT" { self.Connect(w, r) } else if r.URL.IsAbs() { // This is an error if is not empty on Client r.RequestURI = "" // If no Accept-Encoding header exists, Transport will add the headers it can accept // and would wrap the response body with the relevant reader. r.Header.Del("Accept-Encoding") // curl can add that, see // http://homepage.ntlworld.com/jonathan.deboynepollard/FGA/web-proxy-connection-header.html r.Header.Del("Proxy-Connection") // Connection is single hop Header: // http://www.w3.org/Protocols/rfc2616/rfc2616.txt // 14.10 Connection // The Connection general-header field allows the sender to specify // options that are desired for that particular connection and MUST NOT // be communicated by proxies over further connections. r.Header.Del("Connection") self.HTTP(w, r) } else { L.Printf("%s is not a full URL path\n", r.RequestURI) } }
func (lb *BackendLoadBalancer) DoWithLoadBalancer(req *http.Request, useTLS bool) (*http.Response, error) { connectString, err := lb.LoadBalancer.GetConnectAddress() if err != nil { return nil, err } log.Debug("connect string is ", connectString) req.URL.Host = connectString req.Host = connectString var transport *http.Transport if useTLS == true { log.Debug("Configuring TLS transport") transport = lb.httpsTransport req.URL.Scheme = "https" } else { log.Debug("Configuring non-TLS transport") transport = lb.httpTransport req.URL.Scheme = "http" } client := &http.Client{ Transport: transport, } req.RequestURI = "" //Must clear when using http.Client return ctxhttp.Do(req.Context(), client, req) }
func (p *Proxy) ServeHTTP(w http.ResponseWriter, req *http.Request) { log.Info("http: %s %s", req.Method, req.URL) if req.Method == "CONNECT" { p.Connect(w, req) return } req.RequestURI = "" for _, h := range hopHeaders { if req.Header.Get(h) != "" { req.Header.Del(h) } } resp, err := p.transport.RoundTrip(req) if err != nil { log.Error("%s", err) w.WriteHeader(http.StatusInternalServerError) return } defer resp.Body.Close() copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) _, err = sutils.CoreCopy(w, resp.Body) if err != nil { log.Error("%s", err) return } return }
func HandleEndpoint(w http.ResponseWriter, r *http.Request) { bourl, err := GetTargetDiscovery(r.URL.Path) if err != nil { log.Error(err) http.Error(w, err.Error(), 500) return } r.RequestURI = "" r.URL.Scheme = bourl.Scheme r.URL.Host = bourl.Host r.URL.Path = bourl.Path client := &http.Client{} // issue request to remote resp, err := client.Do(r) if err != nil { log.Error(err) http.Error(w, "internal service error", 500) return } defer resp.Body.Close() w.Header().Add("Content-Type", resp.Header.Get("Content-Type")) io.Copy(w, resp.Body) }
// Director is required by the proxy; it rewrites the URL // before the proxy operates func (p S3ReverseProxy) Director(req *http.Request) { // we need to rewrite the URL but also S3 insists on having // the host and requesturi correct. p.RewriteUrl(req.URL) req.RequestURI = req.URL.Path req.Host = req.URL.Host }
// See https://golang.org/src/net/http/httputil/reverseproxy.go func (p *OstrogoProxy) Serve(rw http.ResponseWriter, in *http.Request) { out := new(http.Request) *out = *in // Shallow copy apparently // It's an error for RequestURI to be set in a client request out.RequestURI = "" out.URL.Scheme = "http" out.URL.Host = in.Host // From the Host header out.URL.Path = in.URL.Path log.Println("Forwarding: ", out.URL) // XXX Query string resp, err := p.Client.Do(out) if err != nil { log.Println("Do: ", err) return } fmt.Println(resp) // rw.WriteHeader(resp.Status) // b, err := resp.Body.Read() // if err != nil { // log.Println("Do: ", err) // return // } resp.Write(rw) }
// proxyHTTP will proxy the http.Request r to the new hos // This does modify r in the process of proxying the request func (self *Proxy) proxyHTTP(w http.ResponseWriter, r *http.Request) { r.Header.Add("X-Forwarded-Host", r.Host) r.Header.Add("X-Forwarded-For", r.RemoteAddr) r.Host = self.Target r.URL.Host = self.Target // Reset Request properteis for Client r.URL.Scheme = "http" r.RequestURI = "" resp, err := self.Client.Do(r) if err != nil { http.Error(w, BAD_GATEWAY, http.StatusBadGateway) return } // Copy response header for key, _ := range resp.Header { w.Header().Set(key, resp.Header.Get(key)) } w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) }
func forwardRequest(r *http.Request, ip string, destport int, client http.Client, requesturl string, responseChannel chan int, wg *sync.WaitGroup) { defer wg.Done() r.Host = ip r.RequestURI = "" newURL, err := url.Parse(fmt.Sprintf("http://%v:%d%v", ip, destport, requesturl)) if err != nil { log.Printf("Error parsing URL: %s\n", err) if *debug { log.Printf("For URL: %s\n", fmt.Sprintf("http://%v:%d%v", ip, destport, requesturl)) } responseChannel <- 500 return } r.URL = newURL response, err := client.Do(r) if err != nil { log.Printf("Error sending request: %s\n", err) if *debug { log.Printf("For URL: %s\n", r.URL) } responseChannel <- 500 return } io.Copy(ioutil.Discard, response.Body) defer response.Body.Close() return }
// HTTP proxy accepts requests with following two types: // - CONNECT // Generally, this method is used when the client want to connect server with HTTPS. // In fact, the client can do anything he want in this CONNECT way... // The request is something like: // CONNECT www.google.com:443 HTTP/1.1 // Only has the host and port information, and the proxy should not do anything with // the underlying data. What the proxy can do is just exchange data between client and server. // After accepting this, the proxy should response // HTTP/1.1 200 OK // to the client if the connection to the remote server is established. // Then client and server start to exchange data... // // - non-CONNECT, such as GET, POST, ... // In this case, the proxy should redo the method to the remote server. // All of these methods should have the absolute URL that contains the host information. // A GET request looks like: // GET weibo.com/justmao945/.... HTTP/1.1 // which is different from the normal http request: // GET /justmao945/... HTTP/1.1 // Because we can be sure that all of them are http request, we can only redo the request // to the remote server and copy the reponse to client. // func (self *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { use := (self.Blocked(r.URL.Host) || self.Mode == NormalSrv) && r.URL.Host != "" L.Printf("[%s] %s %s %s\n", AccessType(use), r.Method, r.RequestURI, r.Proto) if r.Method == "CONNECT" { if use { self.SSH.Connect(w, r) } else { err := self.Direct.Connect(w, r) if err == ErrShouldProxy { self.SSH.Connect(w, r) } } } else if r.URL.IsAbs() { // This is an error if is not empty on Client r.RequestURI = "" RemoveHopHeaders(r.Header) if use { self.SSH.ServeHTTP(w, r) } else { err := self.Direct.ServeHTTP(w, r) if err == ErrShouldProxy { self.SSH.ServeHTTP(w, r) } } } else if r.URL.Path == "/reload" { self.reload(w, r) } else { L.Printf("%s is not a full URL path\n", r.RequestURI) } }
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { sutils.Info(r.Method, r.URL) if r.Method == "CONNECT" { p.Connect(w, r) return } r.RequestURI = "" r.Header.Del("Accept-Encoding") r.Header.Del("Proxy-Connection") r.Header.Del("Connection") resp, err := tspt.RoundTrip(r) if err != nil { sutils.Err(err) return } defer resp.Body.Close() resp.Header.Del("Content-Length") for k, vv := range resp.Header { for _, v := range vv { w.Header().Add(k, v) } } w.WriteHeader(resp.StatusCode) _, err = sutils.CoreCopy(w, resp.Body) if err != nil { sutils.Err(err) return } return }
func proxyAsync(engine *cluster.Engine, w http.ResponseWriter, r *http.Request, callback func(*http.Response)) error { // RequestURI may not be sent to client r.RequestURI = "" client, scheme := engine.HTTPClientAndScheme() r.URL.Scheme = scheme r.URL.Host = engine.Addr log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Debug("Proxy request") resp, err := client.Do(r) if err != nil { return err } copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(NewWriteFlusher(w), resp.Body) if callback != nil { callback(resp) } // cleanup resp.Body.Close() return nil }
func (rrlb *RoundRobinLoadBalancer) ServeHTTP(response http.ResponseWriter, request *http.Request) { _, endpoint, _ := rrlb.NextEndpoint() fmt.Println("Next Endpoint => " + net.JoinHostPort(endpoint.host.String(), endpoint.port)) request.Header.Add("X-FORWARDED-FOR", request.RemoteAddr) request.Header.Add("Server", "Go Load Balancer") fmt.Println(request.Proto) client := &http.Client{} newRequest := new(http.Request) *newRequest = *request fmt.Println("Request URI => " + request.RequestURI) uri, _ := url.ParseRequestURI(request.RequestURI) if len(uri.Scheme) == 0 { uri.Scheme = "http" } newRequest.URL = uri newRequest.URL.Host = net.JoinHostPort(endpoint.host.String(), endpoint.port) newRequest.URL.User = request.URL.User newRequest.RequestURI = "" clientResponse, _ := client.Do(newRequest) clientResponse.Write(response) }
// doRequest performs original request and returns response that should be returned to client and error (if there is one) func (d *DBClient) doRequest(request *http.Request) (*http.Response, error) { // We can't have this set. And it only contains "/pkg/net/http/" anyway request.RequestURI = "" if d.Cfg.Middleware != "" { // middleware is provided, modifying request var payload Payload rd, err := getRequestDetails(request) if err != nil { return nil, err } payload.Request = rd c := NewConstructor(request, payload) err = c.ApplyMiddleware(d.Cfg.Middleware) if err != nil { log.WithFields(log.Fields{ "mode": d.Cfg.Mode, "error": err.Error(), "host": request.Host, "method": request.Method, "path": request.URL.Path, }).Error("could not forward request, middleware failed to modify request.") return nil, err } request, err = c.ReconstructRequest() if err != nil { return nil, err } } resp, err := d.HTTP.Do(request) if err != nil { log.WithFields(log.Fields{ "mode": d.Cfg.Mode, "error": err.Error(), "host": request.Host, "method": request.Method, "path": request.URL.Path, }).Error("could not forward request, failed to do an HTTP request.") return nil, err } log.WithFields(log.Fields{ "mode": d.Cfg.Mode, "host": request.Host, "method": request.Method, "path": request.URL.Path, }).Debug("response from external service got successfuly!") resp.Header.Set("hoverfly", "Was-Here") return resp, nil }
func (sh *SlashHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if req.URL.Path != "/" { req.URL.Path = strings.TrimRight(req.URL.Path, "/") req.RequestURI = req.URL.RequestURI() } sh.Handler.ServeHTTP(rw, req) }
func (c basePathChopper) ServeHTTP(w http.ResponseWriter, r *http.Request) { // if request path starts with given base path if idx := c.pattern.FindStringSubmatchIndex(r.URL.Path); len(idx) != 0 && idx[0] == 0 { r.URL.Path = r.URL.Path[idx[1]:] r.RequestURI = r.RequestURI[idx[1]:] } c.delegate.ServeHTTP(w, r) }
/** * @brief 重设Request, * * @param http.Request * @param * @param error * * @return */ func ResetRequest(request *http.Request, hostAddress string) (*http.Request, error) { newUrl, err := url.Parse(hostAddress + request.RequestURI) // 清除RequestURI request.RequestURI = "" // 重新设置地址 request.URL = newUrl return request, err }
func (p *PrefixRewriteRule) TransformRequest(r *http.Request) { r.URL.Path = p.ProxiedPathPrefix + r.URL.Path[len(p.SourcePathPrefix):len(r.URL.Path)] r.RequestURI = "" if p.ProxiedAttachHeaders != nil { for k, v := range p.ProxiedAttachHeaders { r.Header[k] = v } } }