func serveProgressHtml(backend backend, w http.ResponseWriter, req *http.Request) bool { // Only do this for modern browsers. useragent := req.Header.Get("User-Agent") if !strings.Contains(useragent, "Mozilla") || isWebsocket(req) { return false } // TODO: Not for images and those kind of stuff? // Only show when we're provisioning if backend.IsReady() { return false } info := backend.GetInfo() // Okey, we're the ones sending the data. w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate") w.Header().Add("Pragma", "no-cache") w.Header().Add("Expires", "0") // Serve custom progress file? if info.ProgressPage != nil && info.ProgressPage.Filename != "" { http.ServeFile(w, req, info.ProgressPage.Filename) } else if info.ProgressPage != nil && info.ProgressPage.Url != "" { director := func(req *http.Request) { req.URL, _ = url.Parse(info.ProgressPage.Url) req.Host = req.URL.Host if info.ProgressPage.Hostname != "" { req.Host = info.ProgressPage.Hostname } } proxy := &httputil.ReverseProxy{Director: director} proxy.ServeHTTP(w, req) } else { templateVars := make(map[string]string) templateVars["BackgroundColor"] = "#41964B" if info.ProgressPage != nil && info.ProgressPage.Style != nil { if info.ProgressPage.Style.BackgroundColor != "" { templateVars["BackgroundColor"] = info.ProgressPage.Style.BackgroundColor } } tmpl, err := template.New("test").Parse(contents) if err != nil { log.Panicf("Failed to parse template: %v", err) } err = tmpl.Execute(w, templateVars) if err != nil { io.WriteString(w, "Failed to render template") } } return true }
// use specified ip and host func DoHttpGetEx(host, ip, url string) (b *bytes.Buffer, err error) { var ( req *http.Request resp *http.Response ) lastIdx := strings.LastIndex(ip, ":") if lastIdx == strings.Index(ip, ":") { lastIdx = len(ip) } ip2 := string([]byte(ip[7:lastIdx])) url2 := replaceHostWithIP(url, host, ip2) if req, err = http.NewRequest("GET", url2, nil); err != nil { return } req.Host = host if resp, err = http.DefaultClient.Do(req); err != nil { return } defer resp.Body.Close() b = new(bytes.Buffer) io.Copy(b, resp.Body) return }
// do an HTTP request to a server and returns the response object and the // complete response body. There's no need to close the response body as this // will have been done. func do(method, req_body, host, ua, uri string, extraHeaders map[string]string) (*http.Response, []byte, error) { var err error var req *http.Request if strings.EqualFold("POST", method) || strings.EqualFold("PUT", method) { req, err = http.NewRequest(method, uri, strings.NewReader(req_body)) } else { req, err = http.NewRequest(method, uri, nil) } if err != nil { return nil, nil, err } if host != "" { req.Host = host } if ua != "" { req.Header["User-Agent"] = []string{ua} } for k, v := range extraHeaders { req.Header.Add(k, v) } resp, err := transport.RoundTrip(req) if resp != nil { defer resp.Body.Close() } if err != nil { return resp, nil, err } body, err := ioutil.ReadAll(resp.Body) return resp, body, err }
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 }
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.URL.Scheme = u.Scheme outReq.URL.Host = u.Host // workaround for https://github.com/golang/go/issues/10433 outReq.URL.Opaque = mergeStartingSlashes(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 }
// 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) } }
// This filthy hack works in conjunction with hostPortStrip to restore the // original request host after mux match. func revertOriginalHost(r *http.Request) { original := r.Header.Get("_devd_original_host") if original != "" { r.Host = original r.Header.Del("_devd_original_host") } }
func (p *WebsocketProxy) Proxy(w http.ResponseWriter, r *http.Request) { hj, ok := w.(http.Hijacker) if !ok { log.Println("hijack assertion failed", r.Host, r.URL.Path) p.handler.ServeHTTP(w, r) // last-ditch effort as plain http return } conn, rw, err := hj.Hijack() if err != nil { log.Println("hijack failed", r.Host, r.URL.Path, err) p.handler.ServeHTTP(w, r) // last-ditch effort as plain http return } defer conn.Close() rw.Flush() wrapreq := new(http.Request) wrapreq.Proto = "HTTP/1.1" wrapreq.ProtoMajor, wrapreq.ProtoMinor = 1, 1 wrapreq.Method = "WEBSOCKET" wrapreq.Host = r.Host const dummy = "/" wrapreq.URL = &url.URL{Path: dummy} var buf bytes.Buffer r.Write(&buf) wrapreq.Body = ioutil.NopCloser(io.MultiReader(&buf, conn)) resp, err := p.transport.RoundTrip(wrapreq) if err != nil || resp.StatusCode != 200 { io.WriteString(conn, "HTTP/1.0 503 Gateway Failed\r\n") io.WriteString(conn, "Connection: close\r\n\r\n") return } defer resp.Body.Close() io.Copy(conn, resp.Body) }
// Sets the Authorization header on the request to use the provided token. // Will also re-write the host value of the request URL to use the value // provided in the TokenAuth. func (a TokenAuth) ApplyAuthentication(r *http.Request) { token := fmt.Sprintf("Token %s", a.Token) r.Header.Add("Authorization", token) r.URL.Host = a.Host r.Host = a.Host }
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) }
// 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...) } }
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.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 = "" // Go doesn't implicitly pass the host header unless you set Host on the request 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 }
// 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 }
// 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 (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) error { transport := new(http.Transport) h, ok := w.(http.Hijacker) if !ok { return errors.New("Unable to hijack connection") } r.Host = srv.addr r.URL.Host = r.Host if len(r.URL.Scheme) == 0 { r.URL.Scheme = "http" } response, err := transport.RoundTrip(r) if err != nil { return err } conn, _, err := h.Hijack() if err != nil { return err } defer conn.Close() defer response.Body.Close() return response.Write(conn) }
func (c *meekConn) roundTrip(sndBuf []byte) (recvBuf []byte, err error) { var req *http.Request var resp *http.Response for retries := 0; retries < maxRetries; retries++ { url := *c.args.url host := url.Host if c.args.front != "" { url.Host = c.args.front } req, err = http.NewRequest("POST", url.String(), bytes.NewReader(sndBuf)) if err != nil { return nil, err } if c.args.front != "" { req.Host = host } req.Header.Set("X-Session-Id", c.sessionID) req.Header.Set("User-Agent", "") resp, err = c.transport.RoundTrip(req) if err != nil { return nil, err } if resp.StatusCode != http.StatusOK { err = fmt.Errorf("status code was %d, not %d", resp.StatusCode, http.StatusOK) time.Sleep(retryDelay) } else { defer resp.Body.Close() recvBuf, err = ioutil.ReadAll(io.LimitReader(resp.Body, maxPayloadLength)) return } } return }
func (p *proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { target := p.targets[rand.Intn(p.count)] if p.forwardHost { r.Host = target.host } target.handler.ServeHTTP(w, r) }
func (t *verboseTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { if t.Verbose { t.dumpRequest(req) } if t.OverrideURL != nil { port := "80" if s := strings.Split(req.URL.Host, ":"); len(s) > 1 { port = s[1] } req = cloneRequest(req) req.Header.Set("X-Original-Scheme", req.URL.Scheme) req.Header.Set("X-Original-Port", port) req.Host = req.URL.Host req.URL.Scheme = t.OverrideURL.Scheme req.URL.Host = t.OverrideURL.Host } resp, err = t.Transport.RoundTrip(req) if err == nil && t.Verbose { t.dumpResponse(resp) } return }
func handler(w http.ResponseWriter, r *http.Request) { //if (r.URL.Path == "/worker.js") { // noOpServiceWorker(w) // return //} r.Host = "" proxy.ServeHTTP(w, r) }
func (rs *RouteServiceConfig) SetupRouteServiceRequest(request *http.Request, args RouteServiceArgs) { rs.logger.Debug("proxy.route-service") request.Header.Set(RouteServiceSignature, args.Signature) request.Header.Set(RouteServiceMetadata, args.Metadata) request.Header.Set(RouteServiceForwardedUrl, args.ForwardedUrlRaw) request.Host = args.ParsedUrl.Host request.URL = args.ParsedUrl }
func makeRequest(params map[string]string) (*http.Request, error) { r := new(http.Request) r.Method = params["METHOD"] if r.Method == "" { return nil, errors.New("mongrel2: no METHOD") } r.Proto = params["VERSION"] var ok bool r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto) if !ok { return nil, errors.New("mongrel2: invalid protocol version") } r.Trailer = http.Header{} r.Header = http.Header{} r.Host = params["Host"] r.Header.Set("Referer", params["Referer"]) r.Header.Set("User-Agent", params["User-Agent"]) if lenstr := params["Content-Length"]; lenstr != "" { clen, err := strconv.ParseInt(lenstr, 10, 64) if err != nil { return nil, errors.New("mongrel2: bad Content-Length") } r.ContentLength = clen } for k, v := range params { if !skipHeader[k] { r.Header.Add(k, v) } } // TODO: cookies if r.Host != "" { url_, err := url.Parse("http://" + r.Host + params["URI"]) if err != nil { return nil, errors.New("mongrel2: failed to parse host and URI into a URL") } r.URL = url_ } if r.URL == nil { url_, err := url.Parse(params["URI"]) if err != nil { return nil, errors.New("mongrel2: failed to parse URI into a URL") } r.URL = url_ } // TODO: how do we know if we're using HTTPS? // TODO: fill in r.RemoteAddr return r, nil }
func resolveHeaders(req *http.Request, headers headers) { for name, value := range headers { req.Header.Set(name, value) } if host, ok := headers["Host"]; ok { req.Host = host } }
func (h *reverseProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if ip := r.Header.Get("X-Real-Ip"); len(ip) > 0 { r.RemoteAddr = ip } if host := r.Header.Get("X-Forwarded-Host"); len(host) > 0 { r.Host = host } h.inner.ServeHTTP(w, r) }
func (p proxy) ServeHTTP(res http.ResponseWriter, r *http.Request) { bo := backoff.NewExponentialBackOff() bo.MaxElapsedTime = 5 * time.Second if err := backoff.Retry(func() error { r.URL.Host = base.Host r.URL.Scheme = base.Scheme r.RequestURI = "" r.Host = base.Host suppliedToken := r.URL.Query().Get("token") if authCookie, err := r.Cookie("grafana-proxy-auth"); err == nil { suppliedToken = authCookie.Value } if cfg.Token != "" && suppliedToken != cfg.Token { http.Error(res, "Please add the `?token=xyz` parameter with correct token", http.StatusForbidden) return nil } resp, err := client.Do(r) if err != nil { return err } defer resp.Body.Close() res.Header().Del("Content-Type") for k, v := range resp.Header { for _, v1 := range v { res.Header().Add(k, v1) } } if r.URL.Query().Get("token") != "" { http.SetCookie(res, &http.Cookie{ Name: "grafana-proxy-auth", Value: r.URL.Query().Get("token"), MaxAge: 31536000, // 1 Year Path: "/", }) } if resp.StatusCode == 401 { loadLogin() return fmt.Errorf("Need to relogin") } res.WriteHeader(resp.StatusCode) written, _ := io.Copy(res, resp.Body) log.Printf("%s %s?%s %d %d\n", r.Method, r.URL.Path, r.URL.RawQuery, resp.StatusCode, written) return nil }, bo); err != nil { http.Error(res, fmt.Sprintf("Woot?\n%s", err), http.StatusInternalServerError) } }
func (h protoHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { r.Header.Set(xForwardedProto, h.proto) // TODO(jmhodges): gross hack in order to get ServeMux to match ports // See https://golang.org/issue/10463 host, _, err := net.SplitHostPort(r.Host) if err == nil { r.Host = host } h.inner.ServeHTTP(w, r) }
func reverseProxy(w http.ResponseWriter, req *http.Request) { logRequest(req) if rSensitivePath.MatchString(req.URL.Path) { w.WriteHeader(http.StatusForbidden) return } outReq := new(http.Request) outReq.Method = req.Method outReq.URL = &url.URL{ Scheme: "http", Host: host, Path: req.URL.Path, RawQuery: req.URL.RawQuery, } outReq.Proto = "HTTP/1.1" outReq.ProtoMajor = 1 outReq.ProtoMinor = 1 outReq.Header = make(http.Header) outReq.Body = req.Body outReq.ContentLength = req.ContentLength outReq.Host = host for _, h := range removeHeaders { req.Header.Del(h) } copyHeader(outReq.Header, req.Header) outReq.Header.Set("Host", host) outReq.Header.Set("Referer", baseURL) outReq.Header.Set("Origin", baseURL) resp, err := send(outReq) if err != nil { log.Printf("proxy error: %v", err) w.WriteHeader(http.StatusInternalServerError) return } defer resp.Body.Close() for _, h := range removeHeaders { resp.Header.Del(h) } if loc := resp.Header.Get("Location"); loc != "" { if u, err := url.Parse(loc); err == nil && u.Host == host { u.Scheme = "http" u.Host = req.Host resp.Header.Set("Location", u.String()) } } copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) }
func (self *HttpServer) request(w http.ResponseWriter, r *http.Request) { whitelisthosts := self.vip.GetStringSlice("whitelisthosts") if self.MatchHost(whitelisthosts, r.Host) == false { w.WriteHeader(http.StatusForbidden) w.Write([]byte("sorry '" + r.Host + "' is not in whitelist")) return } upstreams := self.vip.GetStringMapString("httpservers.hs1.upstreams") upstream, ok := upstreams[r.Host] if ok == false { w.WriteHeader(http.StatusForbidden) w.Write([]byte("sorry '" + r.Host + "' have not set upstream")) return } r.RequestURI = "" dialer := self.dialerpool.Get(upstream) if dialer == nil { glog.Errorln("get empty from dialer pool ") return } transport := &http.Transport{ Proxy: nil, Dial: dialer.Dial, TLSHandshakeTimeout: 10 * time.Second, } client := &http.Client{Transport: transport} client.CheckRedirect = func(req *http.Request, via []*http.Request) error { return utils.ErrHttpRedirect } if r.URL.Scheme == "" { r.URL.Scheme = "http" } r.Host = upstream r.URL.Host = r.Host resp, err := client.Do(r) if err != nil && resp == nil { http.Error(w, "Error contacting backend server.", 500) glog.Errorf("Error connect backend %s: %v", r.RequestURI, err) return } defer resp.Body.Close() for k, v := range resp.Header { for _, vv := range v { w.Header().Add(k, vv) } } w.WriteHeader(resp.StatusCode) _, err = io.Copy(w, resp.Body) if err != nil { glog.V(0).Infoln("io copy error ", err) } }
func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, reader io.Reader, writer io.Writer) error { if len(request.URL.Host) <= 0 { response := generateResponse(400, "Bad Request") return response.Write(writer) } request.Host = request.URL.Host StripHopByHopHeaders(request) ray := s.packetDispatcher.DispatchToOutbound(ctx) input := ray.InboundInput() output := ray.InboundOutput() requestDone := signal.ExecuteAsync(func() error { defer input.Close() requestWriter := bufio.NewWriter(buf.NewBytesWriter(ray.InboundInput())) err := request.Write(requestWriter) if err != nil { return err } if err := requestWriter.Flush(); err != nil { return err } return nil }) responseDone := signal.ExecuteAsync(func() error { responseReader := bufio.OriginalReader(buf.NewBytesReader(ray.InboundOutput())) response, err := http.ReadResponse(responseReader, request) if err != nil { log.Warning("HTTP: Failed to read response: ", err) response = generateResponse(503, "Service Unavailable") } responseWriter := bufio.NewWriter(writer) if err := response.Write(responseWriter); err != nil { return err } if err := responseWriter.Flush(); err != nil { return err } return nil }) if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil { log.Info("HTTP|Server: Connecton ending with ", err) input.CloseError() output.CloseError() return err } return nil }
// ModifyRequest sets the header at name with value on the request. func (m *modifier) ModifyRequest(_ *martian.Context, req *http.Request) error { // Host is treated differently by the http package and the header is // explicitly ignored. if m.name == "Host" { req.Host = m.value } else { req.Header.Set(m.name, m.value) } return nil }
// RequestHeader returns a new set of headers from a request. func RequestHeader(req *http.Request) *Header { return &Header{ h: req.Header, host: func() string { return req.Host }, cl: func() int64 { return req.ContentLength }, te: func() []string { return req.TransferEncoding }, setHost: func(host string) { req.Host = host }, setCL: func(cl int64) { req.ContentLength = cl }, setTE: func(te []string) { req.TransferEncoding = te }, } }