@oriolrius/node-red-api-gateway 0.6.4
Node-RED nodes for API gateway functionality
@oriolrius/node-red-api-gateway
A comprehensive Node-RED node package for building enterprise-grade REST APIs with built-in support for authentication, authorization, validation, caching, rate limiting, and OpenAPI documentation.
Features
- API Server: Fastify-powered HTTP server with automatic OpenAPI spec generation
- Endpoint Definition: Declarative API endpoint configuration with JSON Schema validation
- Authentication: OAuth2/OpenID Connect via Keycloak integration
- Authorization: Role/scope-based access control with OPA (Open Policy Agent) support
- Validation: Request/response validation with JSON Schema
- Pagination: Offset-based and cursor-based pagination
- Filtering & Sorting: Configurable field filtering and sorting with SQL clause generation
- Rate Limiting: Token bucket algorithm with per-IP, per-user, or custom key strategies
- Caching: Response caching with ETag support and configurable TTL
- Error Handling: RFC 7807 Problem Details format
- Metrics: Prometheus metrics endpoint for monitoring
- Logging: Structured JSON logging with Pino
Installation
From npm
cd ~/.node-red
npm install @oriolrius/node-red-api-gateway
For Development
cd ~/.node-red
npm install /path/to/node-red-api-gateway
Or using npm link:
# In the node-red-api-gateway directory
npm link
# In your Node-RED user directory
cd ~/.node-red
npm link @oriolrius/node-red-api-gateway
Quick Start
1. Basic API Setup
Drag an apigw-config node onto the canvas and configure:
- API Version:
v1 - Base Path:
/api - OpenAPI Title:
My API
- API Version:
Drag an apigw-server node and configure:
- Port:
3000 - Config: Select your apigw-config node
- Enable Swagger UI:
true
- Port:
Drag an apigw-endpoint node and configure:
- Path:
/hello - Method:
GET - Server: Select your apigw-server node
- Path:
Connect a function node to handle the request:
msg.res.json({ message: "Hello, World!" });
return null;
- Deploy and access:
- API:
http://localhost:3000/api/v1/hello - Swagger UI:
http://localhost:3000/docs - OpenAPI Spec:
http://localhost:3000/openapi.json
- API:
2. Import Example Flows
The package includes several example flows demonstrating different features:
- In Node-RED, click the menu (hamburger icon)
- Select Import > Examples > @oriolrius/node-red-api-gateway
- Choose an example:
- Basic CRUD API - Complete CRUD operations for a products API
- OAuth2 Authenticated API - Keycloak authentication with role-based access
- OPA Protected API - Policy-based access control with Open Policy Agent
- Pagination & Filtering - Advanced list operations with pagination and filtering
Nodes
apigw-config
Configuration node for centralized settings shared across apigw-server and apigw-endpoint nodes.
Database Configuration:
- Database type (PostgreSQL, MSSQL, MySQL, etc.)
- Connection pooling settings
- Credentials (stored securely)
OAuth2/Keycloak Configuration:
- Keycloak URL and realm
- Client ID and secret
- JWT validation settings (issuer, audience, clock tolerance)
OPA Configuration:
- OPA server URL
- Policy path
- Cache TTL and timeout settings
API Settings:
- Version string and base path
- OpenAPI metadata (title, description, contact, license)
Logging:
- Log level (debug, info, warn, error)
- Output format (console, file)
- Header redaction
apigw-server
HTTP server node that hosts your API endpoints.
Configuration:
- Host and port
- Reference to apigw-config node
- OpenAPI specification endpoint (
/openapi.json) - Swagger UI documentation (
/docs) - Prometheus metrics endpoint (
/metrics)
Features:
- Automatic route registration from apigw-endpoint nodes
- Route conflict detection
- Graceful shutdown
apigw-endpoint
Individual API endpoint definition node.
Core Settings:
- HTTP method (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
- Path with parameters (e.g.,
/users/:id) - Success status code
- Response content type
Validation:
- Body schema (JSON Schema)
- Query parameter schema
- Path parameter schema
- Response schemas (for OpenAPI documentation)
Authorization:
- Required scopes/roles
- Scope operator (AND/OR)
CRUD Operations:
- Operation type (list, get, create, update, delete)
- Table name and primary key
- Auto-generate SQL templates
Pagination:
- Style: offset-based or cursor-based
- Default and maximum page size
Filtering & Sorting:
- Configurable filterable fields
- Configurable sortable fields
- Default sort field and direction
Transformation:
- Request transformation (JSONata expression)
- Response transformation (JSONata expression)
- Field mappings
Rate Limiting:
- Requests per time window
- Key type (IP, user, API key, custom)
Caching:
- TTL (time to live)
- Cache key strategy
- Vary headers
- ETag support
Error Handling:
- Error format (RFC 7807, generic, custom)
- Stack trace inclusion (dev mode)
- Custom error code mappings
Examples
Basic CRUD Endpoint
// In your function node connected to an apigw-endpoint
const products = [
{ id: 1, name: "Widget", price: 29.99 },
{ id: 2, name: "Gadget", price: 49.99 }
];
// List endpoint
msg.res.json({
data: products,
total: products.length
});
return null;
Request Validation
Configure the apigw-endpoint with a body schema:
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 },
"price": { "type": "number", "minimum": 0 }
},
"required": ["name", "price"]
}
Invalid requests automatically return 400 errors with validation details.
OAuth2 Protected Endpoint
- Configure apigw-config with Keycloak settings
- Set
requiredScopeson apigw-endpoint (e.g.,admin, user:write) - Access user info in your function:
const auth = msg.req.auth;
if (auth.authenticated) {
console.log('User:', auth.preferredUsername);
console.log('Roles:', auth.roles);
}
Pagination
Enable pagination on list endpoints:
// Pagination context is populated by apigw-endpoint
const { page, limit, offset } = msg.pagination || {};
// Query database with pagination
const results = await db.query(
`SELECT * FROM products LIMIT ${limit} OFFSET ${offset}`
);
const total = await db.query('SELECT COUNT(*) FROM products');
// Use endpoint's helper to generate metadata
const paginationMeta = msg.endpoint.generatePaginationMeta(
msg.pagination,
{ total: total[0].count, results: results.length }
);
msg.res.json({
data: results,
pagination: paginationMeta
});
Rate Limiting
Enable rate limiting on apigw-endpoint:
- Requests:
100 - Window:
60000(1 minute) - Key Type:
ip(oruserfor per-user limits)
Rate limit info is available in msg.rateLimit:
console.log('Remaining requests:', msg.rateLimit.remaining);
Response Caching
Enable caching on apigw-endpoint:
- TTL:
30000(30 seconds) - Key Strategy:
full(includes query string) - Vary Headers:
authorization(for user-specific caching)
The cache context is available in msg.cache:
if (msg.cache.hit) {
console.log('Cache hit! Age:', msg.cache.age);
}
Development
Prerequisites
- Node.js >= 20.0.0
- npm >= 8.0.0
Setup
npm install
Running Tests
# Run unit tests
npm test
# Run tests in watch mode
npm run test:watch
Running End-to-End Tests
# Start the Docker stack (Node-RED, Keycloak, OPA, SQL Server)
npm run docker:e2e:up
# Run e2e tests
npm run test:e2e
# Stop the Docker stack
npm run docker:e2e:down
Linting
# Check for linting errors
npm run lint
# Fix linting errors automatically
npm run lint:fix
Development Node-RED
# Launch a development Node-RED instance
npm run dev
Scripts
Utility scripts are located in the scripts/ directory. See scripts/README.md for details.
Certificate Management
Download SSL certificates from Nginx Proxy Manager for e2e tests:
./scripts/download-apigw-cert.sh
This script uses npm-cli via uvx to download certificates and only updates files if they differ.
Project Structure
node-red-api-gateway/
├── nodes/ # Node-RED nodes
│ ├── api-config.js/html # Configuration node (apigw-config)
│ ├── api-server.js/html # HTTP server node (apigw-server)
│ ├── api-endpoint.js/html # Endpoint definition node (apigw-endpoint)
│ └── icons/ # Node icons
├── lib/ # Shared utility modules
│ ├── path-utils.js # Path manipulation
│ ├── schema-validator.js # JSON Schema validation
│ ├── rate-limiter.js # Token bucket rate limiting
│ ├── response-cache.js # Response caching
│ ├── error-handler.js # Error handling
│ ├── pagination.js # Pagination helpers
│ ├── filtering-sorting.js # Filter/sort parsing
│ ├── crud-generator.js # SQL generation
│ ├── keycloak-client.js # OAuth2/JWT validation
│ ├── opa-client.js # OPA integration
│ ├── openapi-generator.js # OpenAPI spec generation
│ ├── openapi-parser.js # OpenAPI import
│ ├── logger.js # Pino logging
│ └── metrics-collector.js # Prometheus metrics
├── examples/ # Example flows
├── scripts/ # Utility scripts (see scripts/README.md)
├── tests/ # Test suites
│ ├── unit/ # Unit tests
│ └── e2e/ # End-to-end tests
└── package.json
API Reference
Message Properties
When a request hits an apigw-endpoint, the following properties are available on msg:
| Property | Type | Description |
|---|---|---|
msg.req |
Object | Request object (method, url, headers, body, params, query) |
msg.req.auth |
Object | Authentication info (if OAuth2 enabled) |
msg.res |
Object | Response helpers (json, send, status, set, end) |
msg.endpoint |
Object | Endpoint configuration |
msg.pagination |
Object | Parsed pagination params (if enabled) |
msg.filtering |
Object | Parsed filters and WHERE clause (if enabled) |
msg.sorting |
Object | Parsed sorts and ORDER BY clause (if enabled) |
msg.crud |
Object | CRUD operation context (if configured) |
msg.cache |
Object | Cache status (hit, key, age) |
msg.rateLimit |
Object | Rate limit status (allowed, remaining, limit) |
Response Helpers
// Send JSON response
msg.res.json({ data: "value" });
// Set status code
msg.res.status(201).json({ id: 1 });
// Set headers
msg.res.set('X-Custom-Header', 'value');
// End without body
msg.res.status(204).end();
License
MIT
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to the main repository.