Documentation
¶
Overview ¶
Package bifrost provides a cloud-native reverse proxy with support for dynamic routing, GCP authentication, and OpenTelemetry instrumentation.
Bifrost is designed for routing traffic between microservices, particularly in cloud environments like Google Cloud Platform. It offers declarative YAML-based configuration, path parameter mapping, automatic OIDC token injection for service-to-service authentication, and built-in observability through OpenTelemetry.
Basic Usage ¶
Create a configuration and initialize Bifrost:
cfg := &config.Config{
Server: config.Server{
Port: 9000,
AllowedHeaders: []string{"Content-Type", "Authorization"},
},
Routes: []config.Route{
{
ID: "users-api",
Path: "/api/users/{id}",
Methods: []string{"GET", "POST"},
Target: config.Target{
URL: "https://users-service.example.com",
Path: "/v1/users/{id}",
},
},
},
}
logger := slog.Default()
proxy, err := bifrost.New(cfg, logger)
if err != nil {
log.Fatal(err)
}
http.ListenAndServe(":9000", proxy.Handler)
Features ¶
- Declarative routing with path parameter support - Automatic GCP OIDC token injection for Cloud Run and other GCP services - Request timeout configuration (global and per-route) - Header filtering with allowlist support - Request body size limits - Graceful shutdown with in-flight request tracking - OpenTelemetry tracing and metrics integration - Health check endpoint
Configuration ¶
Configuration can be loaded from a YAML file using the config package:
cfg, err := config.Load("config.yaml")
if err != nil {
log.Fatal(err)
}
See the config package documentation for full configuration options.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Bifrost ¶
type Bifrost struct {
// Handler is the HTTP handler that processes incoming requests.
// Use this with http.ListenAndServe or http.Server.
Handler http.Handler
// contains filtered or unexported fields
}
Bifrost represents a configured reverse proxy server instance.
It maintains the HTTP handler, configuration, logger, and tracks active requests for graceful shutdown. The Handler field can be used directly with http.Server or other HTTP server implementations.
func New ¶
New creates a new Bifrost instance from a configuration and logger.
It validates the configuration, sets up all routes with their handlers, configures OpenTelemetry instrumentation for tracing and metrics, and registers a health check endpoint at GET /health.
The returned Bifrost instance is ready to handle HTTP requests through its Handler field.
Returns an error if:
- cfg or logger is nil
- the port is invalid (not between 1 and 65535)
- any route configuration is invalid
- route handlers cannot be created
- duplicate routes are detected
Example:
cfg := &config.Config{Server: config.Server{Port: 8080}}
logger := slog.Default()
proxy, err := New(cfg, logger)
if err != nil {
return err
}
http.ListenAndServe(":8080", proxy.Handler)
func (*Bifrost) ActiveRequests ¶
ActiveRequests returns the current number of in-flight HTTP requests.
This can be useful for monitoring and determining when it's safe to shut down the server. The count is updated atomically and is thread-safe.
func (*Bifrost) Config ¶
Config returns the configuration used by the Bifrost instance.
This provides read-only access to the configuration that was provided during initialization. Modifying the returned configuration will not affect the running proxy.
func (*Bifrost) Shutdown ¶
Shutdown gracefully shuts down the Bifrost instance.
It waits for all in-flight requests to complete before returning. The shutdown process polls active requests every 100ms until all requests have finished or the provided context is cancelled.
Returns nil when all requests complete successfully, or ctx.Err() if the context deadline/cancellation occurs before all requests finish.
Example:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := proxy.Shutdown(ctx); err != nil {
log.Printf("shutdown error: %v", err)
}