func idHandlerFunc(ctx *fasthttp.RequestCtx, idWorker *goflake.IdWorker, retry int) { ua := string(ctx.UserAgent()) var ( id uint64 err error ) for i := 0; i < retry; i++ { id, err = idWorker.GetId(ua) if err == nil { break } } r := map[string]string{ "id": strconv.FormatUint(id, 10), } if strings.HasSuffix(string(ctx.Path()), ".msgpack") { ctx.SetContentType("application/x-msgpack; charset=UTF-8") if err := codec.NewEncoder(ctx, mh).Encode(r); err != nil { ctx.Error(err.Error(), fasthttp.StatusInternalServerError) } } else { ctx.SetContentType("application/json; charset=UTF-8") if err := json.NewEncoder(ctx).Encode(r); err != nil { ctx.Error(fmt.Sprintf(`{"error":"%v"}`, err.Error()), fasthttp.StatusInternalServerError) } } }
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 (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) } }