Documentation
¶
Overview ¶
Package gateway provides a REFERENCE IMPLEMENTATION for API gateway integration with FARP.
⚠️ IMPORTANT: This is NOT production-ready code. It serves as an example/helper to demonstrate how gateways should integrate with FARP.
What This Package Provides ¶
- Example of how to watch for manifest changes - Example of how to convert schemas to routes - Example of how to cache schemas - Integration with the merger package
What This Package Does NOT Provide ¶
- Complete HTTP client (HTTP schema fetch implemented) - Production-ready error handling - Gateway-specific route application - Health monitoring - Load balancing logic - Retry logic with exponential backoff - Circuit breaker patterns
For Production Gateways ¶
Real gateway implementations (Kong, Traefik, Envoy, custom) should:
1. Implement their own HTTP client to fetch schemas 2. Implement their own service discovery watchers (Consul, etcd, K8s, mDNS) 3. Implement gateway-specific route configuration 4. Add production-ready error handling and observability 5. Use this package as a reference/inspiration, not a dependency
See docs/IMPLEMENTATION_RESPONSIBILITIES.md for complete guidance.
Index ¶
- type Client
- func (c *Client) ClearCache()
- func (c *Client) ConvertToRoutes(manifests []*farp.SchemaManifest) []ServiceRoute
- func (c *Client) GenerateMergedOpenAPI(ctx context.Context, serviceName string) (*merger.MergeResult, error)deprecated
- func (c *Client) GenerateMergedSchemas(ctx context.Context, serviceName string) (*merger.MultiProtocolResult, error)
- func (c *Client) GetCachedManifests() []*farp.SchemaManifest
- func (c *Client) GetManifest(instanceID string) (*farp.SchemaManifest, bool)
- func (c *Client) GetManifestsHash() string
- func (c *Client) GetMergedAsyncAPIJSON(ctx context.Context, serviceName string) ([]byte, error)
- func (c *Client) GetMergedOpenAPIJSON(ctx context.Context, serviceName string) ([]byte, error)
- func (c *Client) WatchServices(ctx context.Context, serviceName string, onChange func([]ServiceRoute)) error
- func (c *Client) WatchServicesAtomic(ctx context.Context, serviceName string, handler farp.RouteUpdateHandler) error
- type ClientOption
- type FederatedHandlerOption
- type FederatedSchemaCache
- type FederatedSchemaHandler
- type ServiceRoute
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a reference implementation for API gateway integration. It demonstrates how to watch for service schema changes and provides conversion utilities.
For production use, gateways should implement their own logic tailored to their specific architecture, error handling, and performance requirements.
func NewClient ¶
func NewClient(registry farp.SchemaRegistry, opts ...ClientOption) *Client
NewClient creates a new gateway client with default merger config. Options can be provided to customize the client behavior.
Example:
client := gateway.NewClient(registry, gateway.WithHTTPClient(customHTTPClient))
func NewClientWithConfig ¶
func NewClientWithConfig(registry farp.SchemaRegistry, mergerConfig merger.MergerConfig, opts ...ClientOption) *Client
NewClientWithConfig creates a new gateway client with custom merger config. Options can be provided to customize the client behavior.
Example:
config := merger.DefaultMergerConfig() config.Timeout = 60 * time.Second client := gateway.NewClientWithConfig(registry, config, gateway.WithHTTPClient(customHTTPClient))
func (*Client) ConvertToRoutes ¶
func (c *Client) ConvertToRoutes(manifests []*farp.SchemaManifest) []ServiceRoute
ConvertToRoutes converts service manifests to gateway routes This is a reference implementation - actual gateways should customize this.
func (*Client) GenerateMergedOpenAPI
deprecated
func (*Client) GenerateMergedSchemas ¶
func (c *Client) GenerateMergedSchemas(ctx context.Context, serviceName string) (*merger.MultiProtocolResult, error)
GenerateMergedSchemas generates unified specs for all protocol types from registered services.
func (*Client) GetCachedManifests ¶ added in v1.1.0
func (c *Client) GetCachedManifests() []*farp.SchemaManifest
GetCachedManifests returns a snapshot of all cached manifests.
func (*Client) GetManifest ¶
func (c *Client) GetManifest(instanceID string) (*farp.SchemaManifest, bool)
GetManifest retrieves a cached manifest by instance ID.
func (*Client) GetManifestsHash ¶ added in v1.1.0
GetManifestsHash returns a composite hash of all cached manifests. This hash changes whenever any manifest is added, updated, or removed. Used by FederatedSchemaHandler to detect when re-merging is needed.
func (*Client) GetMergedAsyncAPIJSON ¶ added in v1.1.0
GetMergedAsyncAPIJSON returns the merged AsyncAPI spec as JSON.
func (*Client) GetMergedOpenAPIJSON ¶
GetMergedOpenAPIJSON returns the merged OpenAPI spec as JSON.
func (*Client) WatchServices ¶
func (c *Client) WatchServices(ctx context.Context, serviceName string, onChange func([]ServiceRoute)) error
WatchServices watches for service registrations and schema updates. onChange is called only when the computed route table actually changes, preventing unnecessary route remounts that cause intermittent 404s.
Route change detection uses two strategies:
- Fast path: compare RoutesChecksum from manifests (if services provide it)
- Fallback: compute route table hash locally and compare
For atomic route swaps, use WatchServicesAtomic instead.
func (*Client) WatchServicesAtomic ¶ added in v1.1.0
func (c *Client) WatchServicesAtomic(ctx context.Context, serviceName string, handler farp.RouteUpdateHandler) error
WatchServicesAtomic watches for service changes and uses the RouteUpdateHandler for atomic route swaps. This prevents intermittent 404s by staging new routes before removing old ones.
The handler's PrepareRoutes is called first for validation. If it succeeds, CommitRoutes is called to atomically swap the route table. If commit fails, RollbackRoutes is called.
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures a Client.
func WithHTTPClient ¶
func WithHTTPClient(httpClient *http.Client) ClientOption
WithHTTPClient sets a custom HTTP client for schema fetching. This is useful when you need custom authentication, TLS configuration, or other HTTP client settings.
Example:
client := http.Client{
Timeout: 60 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
gatewayClient := gateway.NewClient(registry, gateway.WithHTTPClient(&client))
type FederatedHandlerOption ¶ added in v1.1.0
type FederatedHandlerOption func(*FederatedSchemaHandler)
FederatedHandlerOption configures a FederatedSchemaHandler.
func WithBasePath ¶ added in v1.1.0
func WithBasePath(basePath string) FederatedHandlerOption
WithBasePath sets the base path prefix that will be stripped from incoming request paths before routing. For example, if mounting at "/_farp/federated/" without http.StripPrefix, set this to "/_farp/federated".
type FederatedSchemaCache ¶ added in v1.1.0
type FederatedSchemaCache struct {
// contains filtered or unexported fields
}
FederatedSchemaCache holds pre-serialized merged schemas per protocol. JSON serialization happens once at merge time, not on every HTTP request. The manifestsHash detects when cached data is stale.
type FederatedSchemaHandler ¶ added in v1.1.0
type FederatedSchemaHandler struct {
// contains filtered or unexported fields
}
FederatedSchemaHandler serves federated/merged schema endpoints. It implements http.Handler and should be mounted at a path like /_farp/federated/.
Endpoints:
GET /openapi.json - Merged OpenAPI 3.x specification GET /asyncapi.json - Merged AsyncAPI 2.x specification GET /grpc.json - Merged gRPC service definitions GET /orpc.json - Merged oRPC procedures GET /summary - Merge metadata (services, conflicts, warnings)
Cache invalidation is lazy: manifest changes flow through WatchServices into the Client's manifestCache, changing the composite hash. On the next HTTP request, ensureFresh detects the hash mismatch and triggers a re-merge. There are no background goroutines or timers.
Example usage:
client := gateway.NewClient(registry)
fedHandler := gateway.NewFederatedSchemaHandler(client)
http.Handle("/_farp/federated/", http.StripPrefix("/_farp/federated", fedHandler))
func NewFederatedSchemaHandler ¶ added in v1.1.0
func NewFederatedSchemaHandler(client *Client, opts ...FederatedHandlerOption) *FederatedSchemaHandler
NewFederatedSchemaHandler creates a handler that serves federated schema endpoints. The client must already be configured and watching services.
Example:
handler := gateway.NewFederatedSchemaHandler(client, gateway.WithBasePath("/_farp/federated"))
http.Handle("/_farp/federated/", handler)
func (*FederatedSchemaHandler) Invalidate ¶ added in v1.1.0
func (h *FederatedSchemaHandler) Invalidate()
Invalidate forces the next request to rebuild the federated schemas. Use this when you know manifests have changed outside of the normal WatchServices flow.
func (*FederatedSchemaHandler) LastBuilt ¶ added in v1.1.0
func (h *FederatedSchemaHandler) LastBuilt() time.Time
LastBuilt returns the time the federated schemas were last built. Returns zero time if schemas have never been built.
func (*FederatedSchemaHandler) ServeHTTP ¶ added in v1.1.0
func (h *FederatedSchemaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler. It routes requests to the appropriate pre-serialized schema JSON.
type ServiceRoute ¶
type ServiceRoute struct {
// Path is the route path pattern
Path string
// Methods are HTTP methods for this route (e.g., ["GET", "POST"])
Methods []string
// TargetURL is the backend service URL
TargetURL string
// HealthURL is the health check URL
HealthURL string
// Middleware are middleware names to apply
Middleware []string
// Metadata contains additional route information
Metadata map[string]any
// ServiceName is the name of the backend service
ServiceName string
// ServiceVersion is the version of the backend service
ServiceVersion string
// InstanceID is the ID of the service instance that produced this route
InstanceID string
}
ServiceRoute represents a route configuration for the gateway.