// Strips the query parameters and optionally preserves them in the X-Query-Param-xyz headers. func (f *stripQuery) Request(ctx filters.FilterContext) { r := ctx.Request() if r == nil { return } url := r.URL if url == nil { return } if !f.preserveAsHeader { url.RawQuery = "" return } q := url.Query() for k, vv := range q { for _, v := range vv { if r.Header == nil { r.Header = http.Header{} } r.Header.Add(fmt.Sprintf("X-Query-Param-%s", sanitize(k)), v) } } url.RawQuery = "" }
func getLocation(ctx filters.FilterContext, location *url.URL) string { r := ctx.Request() uc := *location u := &uc if u.Scheme == "" { if r.URL.Scheme != "" { u.Scheme = r.URL.Scheme } else { u.Scheme = "https" } } u.User = r.URL.User if u.Host == "" { u.Host = getRequestHost(r) } if u.Path == "" { u.Path = r.URL.Path } if u.RawQuery == "" { u.RawQuery = r.URL.RawQuery } return u.String() }
// Creates a response from a handler and a request. // // It calls the handler's ServeHTTP method with an internal response // writer that shares the status code, headers and the response body // with the returned response. It blocks until the handler calls the // response writer's WriteHeader, or starts writing the body, or // returns. The written body is not buffered, but piped to the returned // response's body. // // Example, a simple file server: // // var handler = http.StripPrefix(webRoot, http.FileServer(http.Dir(root))) // // func (f *myFilter) Request(ctx filters.FilterContext) { // serve.ServeHTTP(ctx, handler) // } // func ServeHTTP(ctx filters.FilterContext, h http.Handler) { rsp := &http.Response{Header: make(http.Header)} r, w := io.Pipe() d := &pipedResponse{ response: rsp, reader: r, writer: w, headerDone: make(chan struct{})} req := ctx.Request() go func() { h.ServeHTTP(d, req) select { case <-d.headerDone: default: d.WriteHeader(http.StatusOK) } w.CloseWithError(io.EOF) }() <-d.headerDone rsp.Body = d ctx.Serve(rsp) }
func (t *throttle) Response(ctx filters.FilterContext) { switch t.typ { case backendLatency, backendBandwidth, backendChunks: return } rsp := ctx.Response() rsp.Body = t.goThrottle(rsp.Body, true) }
func (t *throttle) Request(ctx filters.FilterContext) { switch t.typ { case latency, bandwidth, chunks: return } req := ctx.Request() req.Body = t.goThrottle(req.Body, false) }
func (f *headerFilter) Request(ctx filters.FilterContext) { if f.typ == requestHeader { req := ctx.Request() if strings.ToLower(f.key) == "host" { req.Host = f.value } req.Header.Add(f.key, f.value) } }
func (f *headerFilter) Request(ctx filters.FilterContext) { if f.typ != requestHeader { return } ctx.Request().Header.Add(f.key, f.value) if strings.ToLower(f.key) == "host" { ctx.SetOutgoingHost(f.value) } }
// Sets the status code and the location header of the response. Marks the // request served. func (f *redirect) Response(ctx filters.FilterContext) { if !f.deprecated { return } u := getLocation(ctx, f.location) w := ctx.ResponseWriter() w.Header().Set("Location", u) w.WriteHeader(f.code) ctx.MarkServed() }
// Request is copied and then modified to adopt changes in new backend func (r *tee) Request(fc filters.FilterContext) { copyOfRequest := cloneRequest(r, fc.Request()) go func() { rsp, err := r.client.Do(©OfRequest) if err != nil { log.Warn("error while tee request", err) } if err == nil { defer rsp.Body.Close() } }() }
// check basic auth func (a *basic) Request(ctx filters.FilterContext) { username := a.authenticator.CheckAuth(ctx.Request()) if username == "" { header := http.Header{} header.Set(ForceBasicAuthHeaderName, a.realmDefinition) ctx.Serve(&http.Response{ StatusCode: http.StatusUnauthorized, Header: header, }) } }
func (c *compress) Response(ctx filters.FilterContext) { rsp := ctx.Response() if !canEncodeEntity(rsp, c.mime) { return } enc := acceptedEncoding(ctx.Request()) if enc == "" { return } responseHeader(rsp, enc) responseBody(rsp, enc, c.level) }
func (f *headerFilter) Request(ctx filters.FilterContext) { switch f.typ { case setRequestHeader: ctx.Request().Header.Set(f.key, f.value) if strings.ToLower(f.key) == "host" { ctx.SetOutgoingHost(f.value) } case appendRequestHeader, depRequestHeader: ctx.Request().Header.Add(f.key, f.value) if strings.ToLower(f.key) == "host" { ctx.SetOutgoingHost(f.value) } case dropRequestHeader: ctx.Request().Header.Del(f.key) } }
func (f *flowId) Request(fc filters.FilterContext) { r := fc.Request() var flowId string if f.reuseExisting { flowId = r.Header.Get(HeaderName) if isValid(flowId) { return } } flowId, err := NewFlowId(f.flowIdLength) if err == nil { r.Header.Set(HeaderName, flowId) } else { log.Println(err) } }
// Serves content from the file system and marks the request served. func (f *static) Response(ctx filters.FilterContext) { r := ctx.Request() p := r.URL.Path if len(p) < len(f.webRoot) { return } ctx.MarkServed() http.ServeFile(ctx.ResponseWriter(), ctx.Request(), path.Join(f.root, p[len(f.webRoot):])) }
// Sets the status code and the location header of the response. Marks the // request served. func (f *redirect) Response(ctx filters.FilterContext) { r := ctx.Request() w := ctx.ResponseWriter() u := f.copyOfLocation() if u.Scheme == "" { if r.URL.Scheme != "" { u.Scheme = r.URL.Scheme } else { u.Scheme = "https" } } u.User = r.URL.User if u.Host == "" { u.Host = getRequestHost(r) } if u.Path == "" { u.Path = r.URL.Path } if u.RawQuery == "" { u.RawQuery = r.URL.RawQuery } w.Header().Set("Location", u.String()) w.WriteHeader(f.code) ctx.MarkServed() }
func (f *headerFilter) Response(ctx filters.FilterContext) { switch f.typ { case setResponseHeader: ctx.Response().Header.Set(f.key, f.value) case appendResponseHeader, depResponseHeader: ctx.Response().Header.Add(f.key, f.value) case dropResponseHeader: ctx.Response().Header.Del(f.key) } }
func (corf *preserveOriginalFilter) Response(ctx filters.FilterContext) { preserveHeader(ctx.OriginalResponse().Header, ctx.Response().Header) }
func (b *breaker) Request(c filters.FilterContext) { c.Serve(b.resp) }
// the filter copies the path parameter 'echo' to the 'X-Echo' header func (f *setEchoHeader) Request(ctx filters.FilterContext) { ctx.Request().Header.Set("X-Echo", ctx.PathParam("echo")) }
func (h *healthCheck) Response(ctx filters.FilterContext) { ctx.Response().StatusCode = http.StatusOK }
// Modifies the path with regexp.ReplaceAll. func (f *modPath) Request(ctx filters.FilterContext) { req := ctx.Request() req.URL.Path = string(f.rx.ReplaceAll([]byte(req.URL.Path), f.replacement)) }
func (preserve filter) Request(ctx filters.FilterContext) { u, err := url.Parse(ctx.BackendUrl()) if err != nil { log.Error("failed to parse backend host in preserveHost filter", err) return } if preserve && ctx.OutgoingHost() == u.Host { ctx.SetOutgoingHost(ctx.Request().Host) } else if !preserve && ctx.OutgoingHost() == ctx.Request().Host { ctx.SetOutgoingHost(u.Host) } }
func (f *customFilter) Request(ctx filters.FilterContext) { ctx.StateBag()["filter called"] = true }
// a simple filter logging the request URLs func (f *customFilter) Request(ctx filters.FilterContext) { log.Println(f.prefix, ctx.Request().URL) }
func (rc *requestCheck) Request(ctx filters.FilterContext) { if !rc.check(ctx.Request()) { ctx.Serve(&http.Response{StatusCode: http.StatusBadRequest}) } }
func (f statusFilter) Response(ctx filters.FilterContext) { ctx.Response().StatusCode = int(f) }
func (f *headerFilter) Response(ctx filters.FilterContext) { if f.typ == responseHeader { ctx.Response().Header.Add(f.key, f.value) } }
// Redirect implements the redirect logic as a standalone function. func Redirect(ctx filters.FilterContext, code int, location *url.URL) { u := getLocation(ctx, location) ctx.Serve(&http.Response{ StatusCode: code, Header: http.Header{"Location": []string{u}}}) }