adapters

package
v1.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 6, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

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:

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

func WrapMiddleware(mw func(http.Handler) http.Handler) celeris.HandlerFunc

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

func WithErrorHandler(f func(http.ResponseWriter, *http.Request, error)) Option

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

func WithModifyRequest(f func(*http.Request)) Option

WithModifyRequest registers a function that mutates the outbound request before it is sent to the target.

func WithModifyResponse

func WithModifyResponse(f func(*http.Response) error) Option

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL