fasthttp
The fasthttp router is in its own package, so net/http programs never link fasthttp:
import "github.com/vardius/gorouter/v5/fastrouter"It has the same methods, options and matching rules as the net/http router. Handlers are fasthttp.RequestHandlers, and middleware is func(fasthttp.RequestHandler) fasthttp.RequestHandler.
Pass the router to fasthttp as r.HandleFastHTTP.
// Command fasthttp is the hello example on fasthttp, with a middleware and a mounted sub-router.package main
import ( "fmt" "log" "time"
"github.com/valyala/fasthttp"
"github.com/vardius/gorouter/v5/fastrouter")
func newRouter() *fastrouter.Router { api := fastrouter.New() api.GET("/users/{id:[0-9]+}", user)
r := fastrouter.New(fastrouter.WithMiddleware(serverHeader)) r.GET("/", index) r.GET("/hello/{name}", hello) r.Mount("/api/v1", api.HandleFastHTTP)
return r}
func index(ctx *fasthttp.RequestCtx) { fmt.Fprintln(ctx, "welcome")}
func hello(ctx *fasthttp.RequestCtx) { fmt.Fprintf(ctx, "hello, %s!\n", fastrouter.Param(ctx, "name"))}
func user(ctx *fasthttp.RequestCtx) { fmt.Fprintf(ctx, "user #%s\n", fastrouter.Param(ctx, "id"))}
// serverHeader runs for every request, including 404 and 405 responses.func serverHeader(next fasthttp.RequestHandler) fasthttp.RequestHandler { return func(ctx *fasthttp.RequestCtx) { ctx.Response.Header.Set("X-Powered-By", "gorouter") next(ctx) }}
func main() { srv := &fasthttp.Server{Handler: newRouter().HandleFastHTTP, ReadTimeout: 5 * time.Second} log.Fatal(srv.ListenAndServe(":8080"))}What differs from net/http
Section titled “What differs from net/http”Params live as long as the handler
Section titled “Params live as long as the handler”fastrouter.Param(ctx, name) returns a value held in a buffer the router reuses once the request is done, which is why routing a request with params allocates nothing.
The value is valid until the handler returns, even if the handler rewrites the path. Copy it with strings.Clone to keep it longer:
r.POST("/jobs/{id}", func(ctx *fasthttp.RequestCtx) { id := strings.Clone(fastrouter.Param(ctx, "id")) go process(id) // outlives the request, so it gets its own copy})The router keeps params in the request’s user values and releases them when fasthttp finishes the request. Calling ctx.ResetUserValues releases them early, so Param returns an empty string after it.
Keep the Allow header on 405
Section titled “Keep the Allow header on 405”ctx.Error resets the whole response, headers included. In a custom 405 handler, write the response with ctx.SetStatusCode and ctx.SetBodyString so the Allow header the router set survives:
r := fastrouter.New(fastrouter.WithMethodNotAllowed(func(ctx *fasthttp.RequestCtx) { ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed) ctx.SetBodyString("method not allowed")}))Mounting
Section titled “Mounting”Mount a sub-router by its handler func:
r.Mount("/api/v1", v1.HandleFastHTTP)r.Mount("/static", fasthttp.FSHandler("./public", 0))fasthttp has one request object, so the mount rewrites its path for the mounted handler, then puts the original path and params back once that handler returns.
Paths are cleaned first
Section titled “Paths are cleaned first”fasthttp decodes the path and collapses // and .. before the router sees it, so /users//7 matches /users/{id} on fasthttp, while on net/http the empty segment matches nothing.