Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Adapters (overview)

In jetwarp, an adapter is the entry-point you use in application code.

An adapter gives you a single, stable API (adapter.Adapter) while delegating the actual routing to a pluggable driver under the hood. Your handlers stay standard net/http (http.Handler / http.HandlerFunc), and you can swap the underlying router framework (stdlib, chi, gin, echo, fiber, …) without rewriting your app.


What an adapter gives you

1) A portable router API

All adapters return the same interface:

  • Use(...) global middleware
  • Group(prefix, ...) scoped prefix + middleware
  • With(...) scoped middleware without changing the prefix
  • Handle(...) / HandleFunc(...) route registration
  • Err() accumulated registration errors
  • plus ServeHTTP so the router itself is an http.Handler

This is the only surface your application should depend on.

2) A strict “no panic” setup experience

Jetwarp treats route registration as input validation, not a crash site:

  • Invalid patterns, unsupported features, or driver failures must accumulate as errors
  • The router must remain usable even after a bad registration
  • You check r.Err() once your setup is done (before serving traffic)

3) Thin packaging (you only pull what you use)

Each adapter lives in its own module (for example adapter/chi, adapter/gin, …), so you don’t download every framework dependency just to use one.


Choosing an adapter

There is no “best” adapter — pick what matches your project and team.

AdapterGood default when…Notes
stdlibyou want the smallest surface area, maximum portabilityBased on net/http routing semantics
chiyou already use chi, or you want a small, idiomatic routerStrong feature set, common in Go services
ginyou’re in the gin ecosystemJetwarp wraps gin while keeping net/http handlers
echoyou’re in the echo ecosystemJetwarp wraps echo while keeping net/http handlers
fiberyou want Fiber’s performance model / ecosystemJetwarp bridges Fiber (not net/http native) to net/http handlers

If you’re not sure, start with stdlib or chi. You can always change later — that’s the point.


Using an adapter

Adapters intentionally keep construction boring:

package main

import (
	"log"
	"net/http"

	"codeberg.org/iaconlabs/jetwarp/adapter/chi"
)

func main() {
	r := chi.New()

	r.HandleFunc(http.MethodGet, "/healthz", func(w http.ResponseWriter, _ *http.Request) {
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte("OK"))
	})

	if err := r.Err(); err != nil {
		log.Fatal(err)
	}

	log.Fatal(http.ListenAndServe(":8080", r))
}

That same application code should work with adapter/stdlib, adapter/gin, adapter/echo, adapter/fiber, etc. (only the import + constructor change).

Middleware support

Jetwarp middleware is expressed via adapter.MW.

Portable middleware

Portable middleware wraps standard net/http middleware (func(http.Handler) http.Handler) and works everywhere:

mw := adapter.HTTP(func(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// before
		next.ServeHTTP(w, r)
		// after
	})
})

r.Use(mw)

Native middleware (framework-specific)

Jetwarp has a design for native/driver middleware, but not every adapter/driver can express it. If a middleware cannot be applied portably, jetwarp will record an error and continue setup (you’ll see it in Err()).

As a rule of thumb: if you want maximum portability, keep middleware portable.

Reading path parameters

Jetwarp’s canonical pattern syntax uses {name} parameters (e.g. /users/{id}), but how you read the value inside a handler depends on the underlying router.

Many adapters bridge parameters into the standard library *http.Request API (r.PathValue("id")) for a consistent user experience. Some frameworks don’t expose this natively, so bridging is handled at the driver level where possible.

If your service depends heavily on params, test your chosen adapter(s) early and keep your handler param access strategy consistent across the project. (Driver capabilities and param rules are covered in the Drivers section of the docs.)

Introspection and escape hatches (optional)

Most application code should never need these, but they exist for tooling and debugging.

Registry snapshots

Some adapter implementations also expose a registry snapshot (the “truth source” for OpenAPI, diagnostics, and other tooling). When supported, you’ll access it via a type assertion to the appropriate optional interface documented in the adapter package.

Engine access

Similarly, some adapters expose the underlying router/engine as any (for debugging or very specific integrations). This is intentionally an escape hatch — if you rely on it, you are stepping outside the portability contract.

Conformance: why adapters are trusted

Jetwarp’s portability promise is enforced by a shared conformance suite (tests/suite). Drivers must pass driver conformance tests for the capabilities they claim. Adapters are also exercised against adapter-level conformance. If something “works in gin but not in chi”, that’s either:

  • a capability you relied on that one adapter doesn’t claim/support, or

  • a bug (and the suite is where we pin it).