Skip to content

Fiber Driver

The Fiber driver adapts generated HTTP and WebSocket routes to github.com/gofiber/fiber/v2.

Install it:

Terminal window
go get github.com/TDB-Group/anvil-http/fiber

Import it as:

import httpfiber "github.com/TDB-Group/anvil-http/fiber"

Pass Fiber’s own configuration directly:

app := anvil.New(
httpfiber.Driver(fiber.Config{
DisableStartupMessage: true,
ProxyHeader: "CF-Connecting-IP",
}),
)

Anvil does not wrap every Fiber option. The Fiber driver accepts Fiber configuration directly. Driver accepts at most one fiber.Config.

The driver can run standalone, but normal Anvil applications let Anvil own the public listener and dispatch selected HTTP traffic into Fiber.

Use DriverWithOptions when the app needs adapter-owned settings beyond fiber.Config:

app := anvil.New(
httpfiber.DriverWithOptions(httpfiber.Options{
Fiber: fiber.Config{
BodyLimit: 16 << 20,
},
TLS: httpfiber.TLSOptions{
CertFile: "cert.pem",
KeyFile: "key.pem",
},
WebSocket: httpfiber.WebSocketOptions{
Origins: []string{"https://app.example.com"},
Compression: true,
},
}),
)

Supported options:

OptionBehavior
FiberNative fiber.Config.
CodecsRequest decoder and response encoder registry.
ErrorPipelineError mapper and observer pipeline. Driver and DriverWithOptions fill this from app.ErrorPipeline() when the option is nil.
TLSCert/key pair used when the Fiber driver is run standalone. In a normal edge app, use app.ListenTLS.
WebSocketOrigin list and compression flag.

The driver sets defensive defaults when Fiber config leaves them empty:

Fiber settingDefault
ReadTimeout30s
WriteTimeout30s
IdleTimeout2m
BodyLimit4 MiB

The driver rejects negative timeouts, negative body limits, incomplete TLS configuration, empty WebSocket origins, nil codec registries, and custom Fiber error handlers. Send domain errors through Anvil’s error pipeline instead of Fiber’s ErrorHandler.

DriverFrom installs an existing transport and sets that transport’s error pipeline to the owning app pipeline. Use httpfiber.NewWithOptions(httpfiber.Options{ErrorPipeline: ...}) when the transport is running standalone or when a test needs to inspect the transport before it is installed.

Fiber config still controls Fiber app behavior when the driver is installed behind Anvil edge. Public listener settings, such as TLS termination and net/http server timeouts, come from Anvil through ListenTLS and WithListener.

BodyLimit is Fiber’s request body limit. 0 selects the driver default of 4 MiB; negative values are rejected.

Generated HTTP routes are registered with Fiber using the generated method and path. Generated WebSocket routes are registered as GET upgrade routes.

Generated code performs route-collision checks before the driver sees a route. The Fiber driver validates the registered route shape and then passes the route to Fiber. It does not re-run Anvil’s compiler diagnostics at runtime.

When installed through anvil.New, Fiber does not own the public listener. Anvil’s edge listener dispatches selected HTTP fallback requests to Fiber through Fiber’s official net/http adapter.

Route matching is Fiber’s route matching. Use Anvil’s generated :param paths; the driver passes those paths directly to Fiber.

Path normalization is not duplicated in this driver. If Fiber treats two paths differently, Anvil does the same when this driver is selected.

Manual duplicate route registration follows Fiber behavior. Generated Anvil code is checked for collisions before emission, so duplicate generated routes fail at compile time. The driver still validates empty method, empty path, nil handler, and invalid middleware values before it hands a route to Fiber.

Handlers return the response body. Metadata lives on ctx.Response():

ctx.Response().Status(http.StatusAccepted)
ctx.Response().Header("X-Request-ID", requestID)
return body, nil

If the handler returns nil and no status was set, the driver sends 204 No Content. If a body is returned and no status was set, it sends 200 OK.

Returned bodies are encoded through the codec registry using the request Accept header.

Invalid response metadata is treated as a handler error. For example, an empty header name or a status code outside 100..999 is sent through the same error pipeline as a returned error.

Mapped HTTP failures are encoded through the same codec registry and request Accept header as normal responses. If that error response cannot be encoded, the driver falls back to HTTP 500 with a fixed JSON internal-error body.

ctx.Response().Stream writes through Fiber’s body stream writer. A stream response cannot also return a separate body.

Calling Stream a second time returns an error immediately and keeps the first stream handler.

Fiber starts the stream through a Fiber-managed callback. Once that callback is running, the driver has no return path for errors from the stream handler. Report important late-stream failures from the stream handler or through your own observer.

Set stream status and headers before the stream starts. Once Fiber begins writing the stream, the response is committed by Fiber. A late stream failure cannot be turned into a different HTTP status or a normal Anvil JSON error body.

Generated sdk.WS routes are registered as Fiber GET routes. A request that hits that path without a WebSocket upgrade receives 426 Upgrade Required.

HTTP middleware runs before the upgrade. The driver snapshots params, query values, headers, and body before handing control to Fiber’s WebSocket runtime so the Anvil context stays usable inside the socket handler.

The driver uses github.com/gofiber/contrib/websocket. socket.Native() returns *websocket.Conn from that package. The portable socket.Write method supports text and binary messages; use socket.Close for close frames. Fiber can surface close, ping, and pong reads through socket.Read, but portable Anvil handlers only write text and binary messages through socket.Write.

For WebSocket handlers, the driver snapshots params, query values, headers, and body before Fiber enters its socket runtime. Use ctx.Request() for those portable values inside the socket handler. ctx.Native() still returns the Fiber context for deliberate driver-specific work, but that ties the handler to Fiber’s context lifetime and reuse rules.

After the upgrade succeeds, a handler error or recovered panic is mapped and published through the global error pipeline, then the socket is closed. The driver cannot turn that failure into an HTTP response because the connection has already moved to WebSocket frames.

ctx.Native() returns *fiber.Ctx.

Once a handler uses Fiber directly, that handler is no longer portable to the standard-library driver or another HTTP driver without changes.

Transport.Test exposes Fiber’s in-process request testing:

transport := httpfiber.New()
response, err := transport.Test(req)

Use DriverFrom when a test needs to install that same transport into an Anvil app.

Standalone mode can call transport.Start(addr) or transport.ServeConn(conn). Start calls Fiber’s Listen or ListenTLS. ServeConn serves one accepted connection through Fiber’s underlying server. Shutdown(ctx) calls ShutdownWithContext and treats Fiber’s “server is not running” shutdown message as a clean stop. In the normal Anvil edge runtime, the public listener belongs to Anvil and the driver is called through ServeHTTP.

httpfiber.RunTestbed(ctx, suite, opts) executes HTTP, GraphQL-over-HTTP, and WebSocket cases against a running server. Anvil defines the testbed model; the Fiber driver executes WebSocket cases because it imports the socket client.

The WebSocket runner converts http URLs to ws and https URLs to wss. It supports scripted text, binary, ping, and close input messages. It asserts text and binary output messages, then checks the optional close code. It does not assert ping or pong output frames.

Each WebSocket case runs with a 10s timeout inside the driver runner. An expected close code of 0 skips close-status assertion. Any non-zero close code makes the runner read one more frame and compare the WebSocket close status.

report, err := httpfiber.RunTestbed(ctx, suite, testbed.RunOptions{
BaseURL: "http://127.0.0.1:8080",
})