gateway

package
v1.3.0 Latest Latest
Warning

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

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

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

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) ClearCache

func (c *Client) ClearCache()

ClearCache clears the schema cache.

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 (c *Client) GenerateMergedOpenAPI(ctx context.Context, serviceName string) (*merger.MergeResult, error)

Deprecated: Use GenerateMergedSchemas for multi-protocol support.

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

func (c *Client) GetManifestsHash() string

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

func (c *Client) GetMergedAsyncAPIJSON(ctx context.Context, serviceName string) ([]byte, error)

GetMergedAsyncAPIJSON returns the merged AsyncAPI spec as JSON.

func (*Client) GetMergedOpenAPIJSON

func (c *Client) GetMergedOpenAPIJSON(ctx context.Context, serviceName string) ([]byte, error)

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:

  1. Fast path: compare RoutesChecksum from manifests (if services provide it)
  2. 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

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.

Jump to

Keyboard shortcuts

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