func (r *RoundRobin) NextServer() (*url.URL, error) { srv, err := r.nextServer() if err != nil { return nil, err } return utils.CopyURL(srv.url), 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.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 }
// In case if server is already present in the load balancer, returns error func (rr *RoundRobin) UpsertServer(u *url.URL, options ...ServerOption) error { rr.mutex.Lock() defer rr.mutex.Unlock() if u == nil { return fmt.Errorf("server URL can't be nil") } if s, _ := rr.findServerByURL(u); s != nil { for _, o := range options { if err := o(s); err != nil { return err } } rr.resetState() return nil } srv := &server{url: utils.CopyURL(u)} for _, o := range options { if err := o(srv); err != nil { return err } } if srv.weight == 0 { srv.weight = defaultWeight } rr.servers = append(rr.servers, srv) rr.resetState() return nil }
// copyRequest makes a copy of the specified request. func (f *websocketForwarder) copyRequest(req *http.Request) (outReq *http.Request) { outReq = new(http.Request) *outReq = *req outReq.URL = utils.CopyURL(req.URL) outReq.URL.Scheme = req.URL.Scheme outReq.URL.Host = req.URL.Host return outReq }
func (s *Buffer) copyRequest(req *http.Request, body io.ReadCloser, bodySize int64) *http.Request { o := *req o.URL = utils.CopyURL(req.URL) o.Header = make(http.Header) utils.CopyHeaders(o.Header, req.Header) o.ContentLength = bodySize // remove TransferEncoding that could have been previously set because we have transformed the request from chunked encoding o.TransferEncoding = []string{} // http.Transport will close the request body on any error, we are controlling the close process ourselves, so we override the closer here o.Body = ioutil.NopCloser(body) return &o }
func (rb *Rebalancer) upsertServer(u *url.URL, weight int) error { if s, i := rb.findServer(u); i != -1 { s.origWeight = weight } meter, err := rb.newMeter() if err != nil { return err } rbSrv := &rbServer{ url: utils.CopyURL(u), origWeight: weight, curWeight: weight, meter: meter, } rb.servers = append(rb.servers, rbSrv) return nil }
// serveHTTP forwards HTTP traffic using the configured transport func (f *httpStreamingForwarder) serveHTTP(w http.ResponseWriter, req *http.Request, ctx *handlerContext) { pw := utils.ProxyWriter{ W: w, } start := time.Now().UTC() reqUrl, err := url.ParseRequestURI(req.RequestURI) if err != nil { log.Errorf("Error parsing Request URI %v, err: %v", req.RequestURI, err) ctx.errHandler.ServeHTTP(w, req, err) return } urlcpy := utils.CopyURL(req.URL) urlcpy.Scheme = req.URL.Scheme urlcpy.Host = req.URL.Host req.URL.Path = reqUrl.Path req.URL.RawQuery = reqUrl.RawQuery revproxy := httputil.NewSingleHostReverseProxy(urlcpy) revproxy.FlushInterval = f.flushInterval //Flush something every 100 milliseconds revproxy.ServeHTTP(w, req) if req.TLS != nil { log.Infof("Round trip: %v, code: %v, Length: %v, duration: %v tls:version: %x, tls:resume:%t, tls:csuite:%x, tls:server:%v", req.URL, pw.Code, pw.Length, time.Now().UTC().Sub(start), req.TLS.Version, req.TLS.DidResume, req.TLS.CipherSuite, req.TLS.ServerName) } else { log.Infof("Round trip: %v, code: %v, Length: %v, duration: %v", req.URL, pw.Code, pw.Length, time.Now().UTC().Sub(start)) } }