Skip to content

Repository files navigation

GatewayKit

A lightweight, config-driven API gateway built for the GatewayKit SWE take-home assessment.

GatewayKit reads a YAML configuration file and routes incoming HTTP requests to upstream services while applying gateway policies such as method filtering, authentication, rate limiting, retries, header transforms, load balancing, and timeout enforcement.

Features

Implemented

  • YAML configuration loading
  • Config path via CLI argument or GATEWAY_CONFIG
  • Configurable gateway port from gateway.port
  • GET /health available regardless of route config
  • Route prefix matching
  • Longest-prefix route selection
  • Method filtering with 405 Method Not Allowed
  • Allow header on method mismatch
  • JSON gateway error responses
  • Basic proxying to upstream services
  • Query string preservation
  • Request body forwarding for body-capable methods
  • Hard 5MB request body limit with 413
  • Hop-by-hop request and response header stripping
  • strip_prefix path rewriting
  • Timeout resolution from route, upstream, global, then default
  • Per-attempt upstream timeout enforcement
  • 502 for upstream network/connect failures
  • 504 for upstream timeouts
  • API key authentication
  • Fixed-window rate limiting
  • Retry-After on 429
  • global_rate_limit as the default inherited route policy
  • Per-route, per-method, per-IP/global rate limit buckets
  • sliding_window accepted and enforced with fixed-window behavior
  • Single upstream URLs
  • Multiple upstream targets
  • Round-robin target selection
  • Weighted round-robin target selection using repeated slots
  • Header transforms for request and response headers
  • Dynamic header transform values: $request_time, $response_time, $route_path
  • Retry policies for configured upstream HTTP statuses
  • Retry of upstream network failures
  • Fixed and exponential retry backoff
  • Self-contained end-to-end test suite with mock upstreams

Partial

  • sliding_window rate limiting is accepted but intentionally uses fixed-window state.
  • Retry support follows config, including for POST, but does not add idempotency protection.
  • Load balancing supports weighted selection but does not perform active health checks.
  • Response forwarding buffers upstream response bodies instead of streaming them.

Deferred

  • True sliding-window rate limiting
  • Active upstream health checks
  • Health-aware load balancing
  • Circuit breaker
  • Request body transformations
  • Response body envelopes
  • Streaming request/response proxying
  • WebSocket support
  • Distributed or multi-process rate limiting
  • Hot config reload
  • Production observability and structured logging

Prerequisites

  • Node.js 20+
  • npm

Installation

npm install

Running The Gateway

Using TypeScript source directly during development:

npm run dev -- ./gateway.yml

Using an environment variable:

GATEWAY_CONFIG=./gateway.yml npm run dev

Using the compiled build:

npm run build
npm start -- ./gateway.yml

The sample config listens on port 8080.

Health Endpoint

The health endpoint is always available regardless of configuration, auth, rate limits, or proxy state.

curl http://localhost:8080/health

Example response:

{
  "status": "healthy",
  "uptime_seconds": 42
}

Running Tests

npm test

Tests automatically:

  • Start mock upstream servers
  • Start the gateway on ephemeral ports
  • Execute end-to-end HTTP requests
  • Verify config normalization, routing, proxying, rate limiting, auth, transforms, retries, and target selection
  • Shut everything down

No external upstream services are required for the test suite.

Docker

Docker is optional, but the repository includes a Dockerfile for running the compiled gateway.

Build the image:

docker build -t gatewaykit .

Run with the included gateway.yml:

docker run --rm -p 8080:8080 gatewaykit

Run with a mounted config file:

docker run --rm -p 8080:8080 -v "$PWD/gateway.yml:/config/gateway.yml:ro" gatewaykit node dist/index.js /config/gateway.yml

Note: the sample gateway.yml points upstreams at localhost ports such as 3001 and 3002. Inside Docker, localhost means the container itself. For real proxy calls from a container, use upstream URLs reachable from the container network.

Example Requests

Proxy Request

curl http://localhost:8080/api/users

API Key Protected Route

curl \
  -H "X-API-Key: sk_live_abc123" \
  http://localhost:8080/api/internal

Rate Limited Route

Repeated requests beyond the configured limit return:

429 Too Many Requests
Retry-After: 60
{
  "error": "rate_limit_exceeded"
}

Oversized Body

Requests larger than 5MB return:

413 Payload Too Large
{
  "error": "payload_too_large"
}

Config Behavior Notes

  • Unknown fields are ignored for forward compatibility.
  • Known advanced fields that are not fully implemented are accepted so the provided schema remains runnable.
  • request_transform.body, response_transform.body, health_check, and circuit_breaker are accepted but deferred.
  • sliding_window rate limits are enforced as fixed-window limits for this take-home.
  • Retries follow route config, including non-idempotent methods like POST; a production gateway would normally require idempotency keys or stricter retry policy controls.
  • Header names are treated case-insensitively by the underlying Headers implementation.
  • Rate limiting uses the socket remote address and ignores X-Forwarded-For.
  • In-memory state is per gateway process. Distributed rate limiting and shared circuit state are out of scope.

Known Limitations

This implementation intentionally prioritizes a reliable gateway core over complete feature coverage.

The most important omitted production features are:

  • Streaming proxy support for very large request and response bodies
  • Active upstream health checks
  • Circuit breaker state
  • True sliding-window rate limiting
  • Request and response body transformations
  • Structured logging, metrics, and tracing
  • TLS termination and HTTP/2

These trade-offs are deliberate for the assessment time box: the implemented features are designed to be clean, testable, and straightforward for another engineer to extend.

About

Minimalistic but high performance API gateway.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages