func requestHandler(ctx *fasthttp.RequestCtx) { fmt.Fprintf(ctx, "Hello, world!\n\n") fmt.Fprintf(ctx, "Request method is %q\n", ctx.Method()) fmt.Fprintf(ctx, "RequestURI is %q\n", ctx.RequestURI()) fmt.Fprintf(ctx, "Requested path is %q\n", ctx.Path()) fmt.Fprintf(ctx, "Host is %q\n", ctx.Host()) fmt.Fprintf(ctx, "Query string is %q\n", ctx.QueryArgs()) fmt.Fprintf(ctx, "User-Agent is %q\n", ctx.UserAgent()) fmt.Fprintf(ctx, "Connection has been established at %s\n", ctx.ConnTime()) fmt.Fprintf(ctx, "Request has been started at %s\n", ctx.Time()) fmt.Fprintf(ctx, "Serial request number for the current connection is %d\n", ctx.ConnRequestNum()) fmt.Fprintf(ctx, "Your ip is %q\n\n", ctx.RemoteIP()) fmt.Fprintf(ctx, "Raw request is:\n---CUT---\n%s\n---CUT---", &ctx.Request) ctx.SetContentType("text/plain; charset=utf8") // Set arbitrary headers ctx.Response.Header.Set("X-My-Header", "my-header-value") // Set cookies var c fasthttp.Cookie c.SetKey("cookie-name") c.SetValue("cookie-value") ctx.Response.Header.SetCookie(&c) }
func (s *Selector) Match(ctx *fasthttp.RequestCtx) (string, bool) { var matchSlice []byte found := false switch s.RequestAttr { case "IP": matchSlice = []byte(ctx.RemoteIP().String()) case "Method": matchSlice = ctx.Method() case "Path": matchSlice = ctx.Path() case "Host": matchSlice = ctx.Host() case "POST": matchSlice = ctx.PostArgs().Peek(s.SubAttr) case "GET": matchSlice = ctx.QueryArgs().Peek(s.SubAttr) case "Param": matchSlice = ctx.PostArgs().Peek(s.SubAttr) if matchSlice == nil { matchSlice = ctx.QueryArgs().Peek(s.SubAttr) } case "Header": matchSlice = ctx.Request.Header.Peek(s.SubAttr) default: log.Println("unknown request attribute:", s.RequestAttr) } if matchSlice != nil && (s.Regexp == nil || s.Regexp.Match(matchSlice)) { found = true } if s.Negate { found = !found } return string(matchSlice), found }
func (p *Proxy) Handler(ctx *fasthttp.RequestCtx) { respState := rule.Evaluate(p.Rules, ctx) if respState == types.SERVED { return } appRequest := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(appRequest) appRequest.Header.SetMethodBytes(ctx.Method()) ctx.Request.Header.CopyTo(&appRequest.Header) if ctx.IsPost() || ctx.IsPut() { appRequest.SetBody(ctx.PostBody()) } resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) err := p.client.Do(appRequest, resp) if err != nil { log.Println("Response error:", err, resp) ctx.SetStatusCode(429) return } resp.Header.CopyTo(&ctx.Response.Header) ctx.SetStatusCode(resp.StatusCode()) resp.BodyWriteTo(ctx) }
func fastHTTPHandler(ctx *fasthttp.RequestCtx) { if string(ctx.Method()) == "GET" { switch string(ctx.Path()) { case "/rest/hello": ctx.Write([]byte("Hello world")) default: ctx.Error("Unsupported path", fasthttp.StatusNotFound) } return } }
//fasthttp func fastHttpRawHandler(ctx *fasthttp.RequestCtx) { if string(ctx.Method()) == "GET" { switch string(ctx.Path()) { case "/hello": if sleepTime > 0 { time.Sleep(sleepTimeDuration) } ctx.Write(message) default: ctx.Error("Unsupported path", fasthttp.StatusNotFound) } return } ctx.Error("Unsupported method", fasthttp.StatusMethodNotAllowed) }
func (l *logAction) Act(ruleName string, ctx *fasthttp.RequestCtx) error { _, err := fmt.Fprintf( l.destination, "[%v] %v %s %s %s%s \"%s\" \"%s\"\n", ruleName, time.Now().Format("2006-01-02 15:04:05.000"), ctx.Request.Header.Peek("X-Forwarded-For"), ctx.Method(), ctx.Host(), ctx.RequestURI(), ctx.PostBody(), ctx.Request.Header.UserAgent(), ) return err }
func (g *Goka) Serve(rCtx *fasthttp.RequestCtx) { c := g.pool.Get().(*Context) h, g := g.router.Find(string(rCtx.Method()), string(rCtx.Path()), c) c.reset(rCtx, g) for i := len(g.middleware) - 1; i >= 0; i-- { h = g.middleware[i](h) } if err := h(c); err != nil { g.httpErrorHandler(err, c) } g.pool.Put(c) }
func requestHandler(ctx *fasthttp.RequestCtx) { headers := http.Header{} ctx.Request.Header.VisitAll(func(key, value []byte) { headers.Add(string(key), string(value)) }) u, err := url.Parse(fmt.Sprint("http://", *upstreamHost, "/", string(ctx.Request.RequestURI()))) if err != nil { ctx.Error("Bad Gateway", fasthttp.StatusBadGateway) log.Print(err) return } req := &http.Request{ Method: string(ctx.Method()), URL: u, Proto: map[bool]string{true: "HTTP/1.1", false: "HTTP/1.0"}[ctx.Request.Header.IsHTTP11()], ProtoMinor: map[bool]int{true: 1, false: 0}[ctx.Request.Header.IsHTTP11()], Header: headers, Body: ioutil.NopCloser(bytes.NewReader(ctx.Request.Body())), ContentLength: int64(ctx.Request.Header.ContentLength()), Host: string(ctx.Request.Header.Host()), } resp, err := upstreamClient.Do(req) if err != nil { ctx.Error("Bad Gateway", fasthttp.StatusBadGateway) log.Print(err) return } defer resp.Body.Close() for k, v := range resp.Header { ctx.Response.Header.Add(k, strings.Join(v, ",")) } io.Copy(ctx.Response.BodyWriter(), resp.Body) }
func (rp *FastReverseProxy) handler(ctx *fasthttp.RequestCtx) { req := &ctx.Request resp := &ctx.Response host := string(req.Header.Host()) uri := req.URI() if host == "__ping__" && len(uri.Path()) == 1 && uri.Path()[0] == byte('/') { resp.SetBody(okResponse) return } reqData, err := rp.Router.ChooseBackend(host) if err != nil { log.LogError(reqData.String(), string(uri.Path()), err) } dstScheme := "" dstHost := "" u, err := url.Parse(reqData.Backend) if err == nil { dstScheme = u.Scheme dstHost = u.Host } else { log.LogError(reqData.String(), string(uri.Path()), err) } if dstHost == "" { dstHost = reqData.Backend } upgrade := req.Header.Peek("Upgrade") if len(upgrade) > 0 && bytes.Compare(bytes.ToLower(upgrade), websocketUpgrade) == 0 { resp.SkipResponse = true rp.serveWebsocket(dstHost, reqData, ctx) return } var backendDuration time.Duration logEntry := func() *log.LogEntry { proto := "HTTP/1.0" if req.Header.IsHTTP11() { proto = "HTTP/1.1" } return &log.LogEntry{ Now: time.Now(), BackendDuration: backendDuration, TotalDuration: time.Since(reqData.StartTime), BackendKey: reqData.BackendKey, RemoteAddr: ctx.RemoteAddr().String(), Method: string(ctx.Method()), Path: string(uri.Path()), Proto: proto, Referer: string(ctx.Referer()), UserAgent: string(ctx.UserAgent()), RequestIDHeader: rp.RequestIDHeader, RequestID: string(req.Header.Peek(rp.RequestIDHeader)), StatusCode: resp.StatusCode(), ContentLength: int64(resp.Header.ContentLength()), } } isDebug := len(req.Header.Peek("X-Debug-Router")) > 0 req.Header.Del("X-Debug-Router") if dstHost == "" { resp.SetStatusCode(http.StatusBadRequest) resp.SetBody(noRouteResponseContent) rp.debugHeaders(resp, reqData, isDebug) endErr := rp.Router.EndRequest(reqData, false, logEntry) if endErr != nil { log.LogError(reqData.String(), string(uri.Path()), endErr) } return } if rp.RequestIDHeader != "" && len(req.Header.Peek(rp.RequestIDHeader)) == 0 { unparsedID, err := uuid.NewV4() if err == nil { req.Header.Set(rp.RequestIDHeader, unparsedID.String()) } else { log.LogError(reqData.String(), string(uri.Path()), fmt.Errorf("unable to generate request id: %s", err)) } } hostOnly, _, _ := net.SplitHostPort(dstHost) if hostOnly == "" { hostOnly = dstHost } isIP := net.ParseIP(hostOnly) != nil if !isIP { req.Header.SetBytesV("X-Host", uri.Host()) req.Header.SetBytesV("X-Forwarded-Host", uri.Host()) uri.SetHost(hostOnly) } client := rp.getClient(dstHost, dstScheme == "https") t0 := time.Now().UTC() err = client.Do(req, resp) backendDuration = time.Since(t0) markAsDead := false if err != nil { var isTimeout bool if netErr, ok := err.(net.Error); ok { markAsDead = !netErr.Temporary() isTimeout = netErr.Timeout() } if isTimeout { markAsDead = false err = fmt.Errorf("request timed out after %v: %s", time.Since(reqData.StartTime), err) } else { err = fmt.Errorf("error in backend request: %s", err) } if markAsDead { err = fmt.Errorf("%s *DEAD*", err) } resp.SetStatusCode(http.StatusServiceUnavailable) log.LogError(reqData.String(), string(uri.Path()), err) } rp.debugHeaders(resp, reqData, isDebug) endErr := rp.Router.EndRequest(reqData, markAsDead, logEntry) if endErr != nil { log.LogError(reqData.String(), string(uri.Path()), endErr) } }
// Handler makes the router implement the fasthttp.ListenAndServe interface. func (r *Router) Handler(ctx *fasthttp.RequestCtx) { if r.PanicHandler != nil { defer r.recv(ctx) } method := string(ctx.Method()) if root := r.trees[method]; root != nil { path := string(ctx.Path()) if f, ps, tsr := root.getValue(path); f != nil { f(ctx, ps) return } else if method != "CONNECT" && path != "/" { code := 301 // Permanent redirect, request with GET method if method != "GET" { // Temporary redirect, request with same method // As of Go 1.3, Go does not support status code 308. code = 307 } if tsr && r.RedirectTrailingSlash { var uri string if len(path) > 1 && path[len(path)-1] == '/' { uri = path[:len(path)-1] } else { uri = path + "/" } ctx.Redirect(uri, code) return } // Try to fix the request path if r.RedirectFixedPath { fixedPath, found := root.findCaseInsensitivePath( CleanPath(path), r.RedirectTrailingSlash, ) if found { uri := string(fixedPath) ctx.Redirect(uri, code) return } } } } // Handle 405 if r.HandleMethodNotAllowed { for method := range r.trees { // Skip the requested method - we already tried this one if method == string(ctx.Method()) { continue } f, _, _ := r.trees[method].getValue(string(ctx.Path())) if f != nil { if r.MethodNotAllowed != nil { r.MethodNotAllowed(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed), fasthttp.StatusMethodNotAllowed) } return } } } // Handle 404 if r.NotFound != nil { r.NotFound(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound), fasthttp.StatusNotFound) } }
// Handler makes the router implement the fasthttp.ListenAndServe interface. func (r *Router) Handler(ctx *fasthttp.RequestCtx) { if r.PanicHandler != nil { defer r.recv(ctx) } path := string(ctx.Path()) method := string(ctx.Method()) if root := r.trees[method]; root != nil { if f, ps, tsr := root.getValue(path); f != nil { f(ctx, ps) return } else if method != "CONNECT" && path != "/" { code := 301 // Permanent redirect, request with GET method if method != "GET" { // Temporary redirect, request with same method // As of Go 1.3, Go does not support status code 308. code = 307 } if tsr && r.RedirectTrailingSlash { var uri string if len(path) > 1 && path[len(path)-1] == '/' { uri = path[:len(path)-1] } else { uri = path + "/" } ctx.Redirect(uri, code) return } // Try to fix the request path if r.RedirectFixedPath { fixedPath, found := root.findCaseInsensitivePath( CleanPath(path), r.RedirectTrailingSlash, ) if found { uri := string(fixedPath) ctx.Redirect(uri, code) return } } } } if method == "OPTIONS" { // Handle OPTIONS requests if r.HandleOPTIONS { if allow := r.allowed(path, method); len(allow) > 0 { ctx.Response.Header.Set("Allow", allow) return } } } else { // Handle 405 if r.HandleMethodNotAllowed { if allow := r.allowed(path, method); len(allow) > 0 { ctx.Response.Header.Set("Allow", allow) if r.MethodNotAllowed != nil { r.MethodNotAllowed(ctx) } else { ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed) ctx.SetContentTypeBytes(defaultContentType) ctx.SetBodyString(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed)) } return } } } // Handle 404 if r.NotFound != nil { r.NotFound(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound), fasthttp.StatusNotFound) } }