Skip to content

Latest commit

 

History

History
162 lines (131 loc) · 7.19 KB

File metadata and controls

162 lines (131 loc) · 7.19 KB

Configuration

Configuration layers, lowest precedence first:

  1. Built-in defaults
  2. gqlgate.yaml (or --config <path>; ./gqlgate.yaml and ./gqlgate.yml are picked up automatically)
  3. GQLGATE_* environment variables
  4. Command-line flags

Flag names are the config paths, so precedence needs no mapping table: --routes.strict_params=false. Only flags you actually pass take effect, so an unset flag never clobbers a file or environment value.

Environment keys lowercase the name and treat a single underscore as a level separator; a double underscore stands for a literal underscore:

Key Environment variable
upstream.url GQLGATE_UPSTREAM_URL
server.max_body_bytes GQLGATE_SERVER_MAX__BODY__BYTES
routes.strict_params GQLGATE_ROUTES_STRICT__PARAMS
routes.pagination_headers.total_count GQLGATE_ROUTES_PAGINATION__HEADERS_TOTAL__COUNT

gqlgate config example prints the full annotated reference, generated from the config structs so it cannot drift from the code. gqlgate config validate checks the effective configuration and exits non-zero with a bulleted list of problems.

upstream

Key Default Meaning
url (required) Base URL of the target GraphQL API
path /graphql Endpoint path relative to url
timeout 25s Per-request timeout for the upstream call
max_idle_conns 100 Idle connections kept alive
strip_headers [] Extra inbound headers never forwarded
forward_response_headers [] Upstream response headers copied to the client
claim_prefix X-Pdbq-Claim- Claim header prefix; inbound headers matching it are always stripped
inject_claims {} Claims gqlgate asserts itself — see security.md
allow_insecure_claims false Permit injection toward a public upstream
request_id_header X-Request-Id Correlation id; generated when absent

server

Key Default Meaning
addr :8080 Listen address
request_timeout 30s Whole-request timeout, upstream call included
max_body_bytes 1048576 Maximum request body size
cors_origins [] Allowed origins (exact, or *). Empty disables CORS entirely
compression false Gzip responses for clients that accept it
shutdown_grace 10s Drain time for in-flight requests after SIGTERM

When CORS is enabled, the pagination headers are added to Access-Control-Expose-Headers automatically — browsers cannot read them otherwise, and collection responses carry their pagination there.

server.openapi

Key Default Meaning
enabled true Serve the generated OpenAPI document
path /openapi.json Where the document is served
title gqlgate Title shown in API documentation
version 1.0.0 Version reported in the info block
description "" Description shown in API documentation
server_url "" Base URL written into the servers block. Empty uses /, so Scalar calls the origin it loaded the document from
include_aliases false Also document the flat /q/ and /m/ routes
allow_any_origin true Serve the document with Access-Control-Allow-Origin: *

The document is rendered from the plan whenever routes are built, so it follows schema reloads automatically and can never describe an endpoint that is not served.

Set server_url when the browser reaches gqlgate at an address other than the one it fetched the document from — behind a proxy, or when Scalar runs on its own port. The bundled compose stack does this from .env.

allow_any_origin affects the document only; the data endpoints still obey server.cors_origins. It is on by default because the document describes exactly what gqlgate routes already prints. Turn it off to keep the API's shape private, and remember that a docs UI on another origin then cannot load it.

gqlgate openapi prints the same document without starting a server, for client generation and CI spec-diffing.

schema

Key Default Meaning
path "" SDL or introspection-JSON file. Empty introspects the upstream at boot
poll_interval 0s Re-introspect on this interval. 0 disables; must be >= 1s otherwise
reload_on_hup true Rebuild the route table on SIGHUP
boot_timeout 30s How long to keep retrying introspection at boot
boot_retry 2s Delay between boot attempts

schema.path accepts either format; the file is sniffed, so no flag says which. Generate one with pdbq schema print --json or pdbq schema print. A file source never retries at boot — a missing file will not fix itself — and never polls, but SIGHUP still reloads it.

routes

Key Default Meaning
resources {} Per-type path segment overrides, e.g. {SpatialRefSy: spatial-ref-sys}
fields {} Per-field route overrides, e.g. {searchPosts: "GET /posts/search"}
ignore [] Fields never exposed
param_aliases {limit: first, skip: offset, sort: orderBy} Query-parameter aliases
upsert_prefixes [upsert] Field-name prefixes identifying upserts
strict_params true Reject query parameters matching no argument
allow_unfiltered_bulk false Permit bulk update/delete with an empty filter
delete_returns_row false Return 200 and the row rather than 204
default_page_size 0 first applied when the client sends no pagination
max_select_depth 5 Maximum ?select= nesting
max_select_fields 200 Maximum ?select= field count
select_cache_size 256 Compiled ?select= documents cached
flat_aliases true Also expose every field at /q/ or /m/

pagination_headers names the response headers carrying connection metadata: total_count (X-Total-Count), has_next_page, has_previous_page, start_cursor, end_cursor, affected_count.

See routing.md for what these do to the route table.

errors

Key Default Meaning
status_map see below extensions.code → HTTP status
include_extensions true Include upstream extensions in error bodies
include_path true Include upstream path in error bodies

The default map covers the PostgreSQL SQLSTATEs pdbq surfaces:

errors:
  status_map:
    "23505": 409  # unique violation
    "23503": 422  # foreign key violation
    "23514": 422  # check violation
    "23502": 422  # not-null violation
    "40001": 503  # serialization failure (with Retry-After)
    "40P01": 503  # deadlock detected
    "42501": 403  # insufficient privilege

Codes not in the map fall back to their SQLSTATE class: 23*409, 22*400. Failing that, gqlgate reads the message for known phrases, and finally splits on whether any data came back — null data means the operation never ran (400), partial data means execution failed server-side (500).

log

Key Default Meaning
level info debug, info, warn, error
format text text or json
requests true One line per request