Search by

phprise / grogu-gateway

esdras-schonevald

A generic gateway for Symfony/ApiPlatform applications based on The OTAKU Manifesto.

Package info

github.com/phprise-foundation/grogu-gateway

Type:project

pkg:composer/phprise/grogu-gateway

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-11 14:59 UTC

This package is auto-updated.

Last update: 2026-10-25 20:32:12 UTC


README

A generic gateway for Symfony/ApiPlatform applications based on the OTAKU Manifesto.

What it does

Grogu is a single entry point in front of many ApiPlatform services. It discovers each service's OpenAPI document at runtime, aggregates every route into one map, and forwards incoming requests to the service that owns the route.

Given enma=https://enma.io and nami=https://nami.io, a request to POST grogu.io/api/order is forwarded to POST nami.io/api/order.

How it works

  1. Bootstrap: reads the GROGU_SERVICES environment variable and builds a ServiceRegistry.
  2. Discovery: for every service, fetches {host}/api/docs.json and extracts its operations.
  3. Aggregation: builds a RouteMap. If two services expose the same method and path, an AmbiguousRouteException is thrown and the gateway refuses to start.
  4. Routing: resolves the incoming request against the map and forwards it to the owner.

Discovery happens on every request, so any change in a service's documentation is reflected immediately without restarting the gateway.

Configuration

Services are configured through the GROGU_SERVICES environment variable as a comma-separated list of name=host pairs:

export GROGU_SERVICES="enma=https://enma.io,nami=https://nami.io,yagami=https://yagami.io"

The host is the origin only (scheme + domain). The path to the OpenAPI document is configured separately through GROGU_SPEC_PATHS, a comma-separated list of candidate paths tried in order until one returns a valid JSON document:

export GROGU_SPEC_PATHS="/api/docs.json,/docs.json,/openapi.json"

This makes the gateway flexible across frameworks: an API Platform service may expose /api/docs.json, while another may expose /docs.json. If GROGU_SPEC_PATHS is not set, it defaults to /api/docs.json.

Different environments can expose different hosts, or omit services entirely (for example, authentication in a development environment).

Authentication

Authentication is optional and pluggable. By default it is disabled (GROGU_AUTH_MODE=none), and the gateway forwards every request untouched.

When enabled, the gateway authenticates the request before forwarding it. The authenticator is a generic HTTP adapter: it extracts a token from a request header, calls a verification URL, and interprets the JSON response. This means the same adapter works with any verification service (KoenmaID, Keycloak, a custom one).

Environment variables

Variable Default Description
GROGU_AUTH_MODE none none (disabled) or http (generic HTTP adapter)
GROGU_AUTH_URL — The verification URL the gateway calls
GROGU_AUTH_HEADER Authorization The request header that carries the token
GROGU_AUTH_PUBLIC_ROUTES — Comma-separated routes that skip authentication

The verification contract

The gateway sends a POST to GROGU_AUTH_URL with a JSON body:

{ "token": "<the token, without the scheme>" }

The verification service must answer with:

{
  "valid": true,
  "subject": "user-123",
  "claims": { "role": "admin" },
  "metadata": { "tenant": "acme" }
}
  • valid (required) — whether the token is accepted.
  • subject — who was authenticated. username is accepted as a fallback.
  • claims — key/value data about the identity.
  • metadata — free-form key/value data for the consumer's own rules.

Any other shape (or valid: false) results in a 401.

Example: KoenmaID

export GROGU_AUTH_MODE=http
export GROGU_AUTH_URL="https://koenma.example.com/token/verify"
export GROGU_AUTH_HEADER="Authorization"
export GROGU_AUTH_PUBLIC_ROUTES="GET /docs,GET /health"

Example: Keycloak (same adapter)

export GROGU_AUTH_MODE=http
export GROGU_AUTH_URL="https://keycloak.example.com/realms/acme/protocol/openid-connect/userinfo"
export GROGU_AUTH_HEADER="Authorization"

Custom authenticators

For cases the HTTP adapter does not cover, implement Phprise\GroguGateway\Domain\Contract\AuthenticatorInterface and wire it in public/index.php through an AuthenticationGate.

Running

composer install
GROGU_SERVICES="nami=https://nami.splitpaybrasil.dev.br" php -S localhost:8000 -t public

Testing

vendor/bin/phpunit
vendor/bin/psalm

Philosophy

We follow The OTAKU Manifesto: Fluid Structure Design. Please read more about it in OTAKU Manifesto. See our security policy in SECURITY.md.