Documentation
¶
Overview ¶
Package adapters bridges stdlib net/http middleware into celeris handler chains.
Use WrapMiddleware to adapt any func(http.Handler) http.Handler into a celeris.HandlerFunc. This enables reuse of existing stdlib middleware such as rs/cors, gorilla/csrf, and similar libraries.
corsHandler := cors.Handler(cors.Options{AllowedOrigins: []string{"*"}})
server.Use(adapters.WrapMiddleware(corsHandler))
Warning: Do not use both adapters.WrapMiddleware with a stdlib CORS library (e.g., rs/cors) AND the native celeris/middleware/cors in the same chain. This produces duplicate Access-Control-* headers and conflicting preflight handling. Use one or the other.
For converting celeris handlers to stdlib, use celeris.ToHandler directly.
How It Works ¶
WrapMiddleware creates a temporary http.ResponseWriter (responseCapture) and reconstructs an *http.Request from the celeris Context. The stdlib middleware runs against these. If the middleware calls the inner handler, control returns to the celeris chain via c.Next(). Any response headers the stdlib middleware set before calling next are copied to the celeris response.
If the stdlib middleware short-circuits (does not call the inner handler), the captured status code, headers, and body are written through celeris.
Performance ¶
WrapMiddleware reconstructs an *http.Request per call, which costs 8-15 heap allocations depending on header count and body presence. For hot-path middleware (e.g., CORS on every request), prefer the native celeris/middleware/cors over adapters.WrapMiddleware(rs/cors) for zero-alloc performance. Use WrapMiddleware for middleware that runs infrequently or where the stdlib library has no native celeris equivalent.
Limitations ¶
The responseCapture used by WrapMiddleware does not implement http.Hijacker or http.Flusher. Stdlib middleware that requires WebSocket upgrade (via Hijack) or streaming flush (via Flush) will not work through WrapMiddleware. For these use cases, implement the middleware natively in celeris.
Reverse Proxy ¶
ReverseProxy creates a handler that forwards requests to a target URL using net/http/httputil.ReverseProxy under the hood:
target, _ := url.Parse("http://backend:8080")
server.Any("/api/*path", adapters.ReverseProxy(target))
Options:
- WithTransport: set a custom http.RoundTripper
- WithModifyRequest: mutate outbound requests (e.g. add headers)
- WithModifyResponse: inspect or modify backend responses before forwarding
- WithErrorHandler: custom error handling for proxy failures
The proxy automatically sets X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto via net/http/httputil.ProxyRequest.SetXForwarded. Panics if target is nil.
ReverseProxy delegates to celeris.Adapt, which buffers the response. Streaming responses (SSE, WebSocket upgrade) are not supported through the proxy.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ReverseProxy ¶
func ReverseProxy(target *url.URL, opts ...Option) celeris.HandlerFunc
ReverseProxy creates a reverse proxy handler that forwards requests to the given target URL. Uses httputil.ReverseProxy under the hood, wrapped via celeris.Adapt for integration with the celeris handler chain.
The proxy sets X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto headers automatically via httputil.ProxyRequest.SetXForwarded.
Panics if target is nil.
Example ¶
package main
import (
"fmt"
"net/http"
"net/url"
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/adapters"
)
func main() {
target, _ := url.Parse("http://backend:8080")
s := celeris.New(celeris.Config{})
s.Any("/api/*path", adapters.ReverseProxy(target,
adapters.WithModifyRequest(func(r *http.Request) {
r.Header.Set("X-Forwarded-By", "celeris")
}),
))
fmt.Println("proxy configured")
}
Output: proxy configured
Example (ModifyResponse) ¶
package main
import (
"fmt"
"net/http"
"net/url"
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/adapters"
)
func main() {
target, _ := url.Parse("http://backend:8080")
s := celeris.New(celeris.Config{})
s.Any("/api/*path", adapters.ReverseProxy(target,
adapters.WithModifyResponse(func(resp *http.Response) error {
resp.Header.Set("X-Proxy", "celeris")
return nil
}),
))
fmt.Println("proxy with response modifier configured")
}
Output: proxy with response modifier configured
func WrapMiddleware ¶
WrapMiddleware adapts a standard net/http middleware (func(http.Handler) http.Handler) into a celeris HandlerFunc. The adapted middleware receives a reconstructed *http.Request and a responseCapture that records headers, status, and body.
When the stdlib middleware calls the inner handler (next.ServeHTTP), the celeris handler chain continues via c.Next(). Any headers the stdlib middleware set on the ResponseWriter before calling next are propagated to the celeris response.
When the stdlib middleware does NOT call the inner handler (e.g., it returns an early 403), the captured response is written back via c.Blob.
Example ¶
package main
import (
"fmt"
"net/http"
"github.com/goceleris/celeris"
"github.com/goceleris/celeris/middleware/adapters"
)
func main() {
// Wrap a standard net/http middleware that adds a header.
addHeader := func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Middleware", "active")
next.ServeHTTP(w, r)
})
}
s := celeris.New(celeris.Config{})
s.Use(adapters.WrapMiddleware(addHeader))
s.GET("/", func(c *celeris.Context) error {
return c.String(200, "ok")
})
fmt.Println("middleware registered")
}
Output: middleware registered
Types ¶
type Option ¶
type Option func(*proxyConfig)
Option configures a ReverseProxy.
func WithErrorHandler ¶
WithErrorHandler registers a function that handles proxy errors (e.g., connection refused, timeout). If not set, the default httputil.ReverseProxy error handler is used.
func WithModifyRequest ¶
WithModifyRequest registers a function that mutates the outbound request before it is sent to the target.
func WithModifyResponse ¶
WithModifyResponse registers a function that modifies the response from the backend before it is forwarded to the client. The function can inspect or modify the response headers and status code. If it returns an error, the error handler is called.
func WithTransport ¶
func WithTransport(rt http.RoundTripper) Option
WithTransport sets the transport used by the reverse proxy.