package fasthttp import ( "net" "net/http" "testing" "github.com/valyala/fasthttp" ) // newCtx builds a RequestCtx the way fasthttp's own tests do. A zero-value ctx // has no remote address, which the net/http adapter dereferences. func newCtx(method, uri string) *fasthttp.RequestCtx { var req fasthttp.Request req.Header.SetMethod(method) req.SetRequestURI(uri) req.SetHost("example.com") ctx := &fasthttp.RequestCtx{} ctx.Init(&req, &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 12345}, nil) return ctx } func TestRouterDispatchesOnMethodAndPath(t *testing.T) { r := NewRouter() r.AddRoute("GET", "/health", func(ctx *fasthttp.RequestCtx) { ctx.SetBodyString("ok") }) ctx := newCtx("GET", "/health") r.HandleRequest(ctx) if got := string(ctx.Response.Body()); got != "ok" { t.Errorf("body = %q; want %q", got, "ok") } // Same path, different method: the route key includes the method. ctx = newCtx("POST", "/health") r.HandleRequest(ctx) if got := ctx.Response.StatusCode(); got != fasthttp.StatusNotFound { t.Errorf("POST /health = %d; want %d", got, fasthttp.StatusNotFound) } } func TestRouterUnknownPathIsNotFound(t *testing.T) { ctx := newCtx("GET", "/missing") NewRouter().HandleRequest(ctx) if got := ctx.Response.StatusCode(); got != fasthttp.StatusNotFound { t.Errorf("status = %d; want %d", got, fasthttp.StatusNotFound) } } // The first middleware passed is the outermost wrapper. func TestChainMiddlewareOrder(t *testing.T) { var order []string tag := func(name string) FastHTTPMiddleware { return func(next RouteHandler) RouteHandler { return func(ctx *fasthttp.RequestCtx) { order = append(order, name) next(ctx) } } } h := ChainMiddleware( func(*fasthttp.RequestCtx) { order = append(order, "handler") }, tag("outer"), tag("inner"), ) h(newCtx("GET", "/")) want := []string{"outer", "inner", "handler"} if len(order) != len(want) { t.Fatalf("order = %v; want %v", order, want) } for i := range want { if order[i] != want[i] { t.Fatalf("order = %v; want %v", order, want) } } } func TestServerStatsCountCompletedRequests(t *testing.T) { s := NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusTeapot) })) ctx := newCtx("GET", "/") s.HandleRequest(ctx) if got := ctx.Response.StatusCode(); got != http.StatusTeapot { t.Errorf("status = %d; want %d", got, http.StatusTeapot) } inFlight, total, last := s.Stats() if inFlight != 0 { t.Errorf("inFlight = %d; want 0 after the request returned", inFlight) } if total != 1 { t.Errorf("total = %d; want 1", total) } if last <= 0 { t.Errorf("last duration = %v; want a positive measurement", last) } }