Quickstart
This page is intentionally small: a first router, a couple of routes, and the one safety check you should not skip.
If you have not installed jetwarp yet, start with the Installation page.
1) Pick an adapter
jetwarp exposes one stable API (adapter.Adapter) and ships multiple adapter packages that bind it to a concrete router
backend (stdlib, chi, gin, echo, fiber, …).
For a first run, chi is a good default:
import "codeberg.org/iaconlabs/jetwarp/adapter/chi"
If you want zero external router dependencies, use the stdlib adapter instead:
import "codeberg.org/iaconlabs/jetwarp/adapter/stdlib"
2) Register routes and middleware
jetwarp’s canonical path patterns use {name} parameters (ServeMux-style). Query strings are not part of matching.
A tiny server might look like this:
package main
import (
"log"
"net/http"
"codeberg.org/iaconlabs/jetwarp/adapter"
"codeberg.org/iaconlabs/jetwarp/adapter/chi"
)
func main() {
r := chi.New()
// Optional: portable net/http middleware (works across all adapters).
r.Use(adapter.HTTPNamed("request_log", func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
log.Printf("%s %s", req.Method, req.URL.Path)
next.ServeHTTP(w, req)
})
}))
// A simple health endpoint.
r.HandleFunc(http.MethodGet, "/healthz", func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write([]byte("ok"))
})
// Path params use {name}. In handlers, prefer stdlib-style PathValue.
r.HandleFunc(http.MethodGet, "/users/{id}", func(w http.ResponseWriter, req *http.Request) {
id := req.PathValue("id")
_, _ = w.Write([]byte("user id = " + id))
})
// ---- do not skip this ----
if err := r.Err(); err != nil {
log.Fatal(err)
}
log.Fatal(http.ListenAndServe(":8080", r))
}
Why req.PathValue("id")?
Some routers (like Gin) do not populate net/http path parameters on their own.
jetwarp drivers bridge captured params into *http.Request so you can read them portably via PathValue across adapters.
3) Fail fast on configuration errors
jetwarp’s registration contract is “no panics”: invalid patterns, unsupported middleware, etc. accumulate into Err().
The recommended default is:
if err := r.Err(); err != nil {
log.Fatal(err)
}
If you want a belt-and-suspenders safety net in addition to the fail-fast check, you can wrap the server handler:
// RefuseOnErr rejects all requests with 503 if Err() is non-nil.
log.Fatal(http.ListenAndServe(":8080", adapter.RefuseOnErr(r, r)))
That wrapper is useful in staging/tests and as a copy/paste-safe pattern.
Next steps
- Groups, With and Middleware — scoping and deterministic middleware order
- OpenAPI — build + attach OpenAPI from the registry snapshot