license: Add MIT license
This commit is contained in:
@@ -5,40 +5,40 @@
|
|||||||
The SecNex API Gateway follows a modular architecture with clear separation of concerns. The system is built using the chi/v5 HTTP router and implements a middleware pipeline pattern.
|
The SecNex API Gateway follows a modular architecture with clear separation of concerns. The system is built using the chi/v5 HTTP router and implements a middleware pipeline pattern.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Client Request │
|
│ Client Request │
|
||||||
└─────────────────────────┬───────────────────────────────────┘
|
└─────────────────────────┬──────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Gateway (chi Router) │
|
│ Gateway (chi Router) │
|
||||||
│ ┌──────────────────────────────────────────────────────┐ │
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
│ │ Middleware Pipeline │ │
|
│ │ Global Middleware Pipeline │ │
|
||||||
│ │ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ │
|
│ │ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ │
|
||||||
│ │ │ Request ID │→ │ Real IP │→ │ Logger │ │ │
|
│ │ │ Request ID │→ │ Real IP │→ │ Logger │ │ │
|
||||||
│ │ └────────────┘ └────────────┘ └──────────────┘ │ │
|
│ │ └────────────┘ └────────────┘ └──────────────┘ │ │
|
||||||
│ └──────────────────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
└─────────────────────────┬───────────────────────────────────┘
|
└─────────────────────────┬──────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Route Handler │
|
│ Route Handler │
|
||||||
│ ┌──────────────────────────────────────────────────────┐ │
|
│ ┌──────────────────────────────────────────────────────┐ │
|
||||||
│ │ Per-Route Middleware Chain │ │
|
│ │ Per-Route Middleware Chain │ │
|
||||||
│ │ ┌────────────┐ ┌─────────┐ ┌──────────────┐ │ │
|
│ │ ┌────────────┐ ┌──────────────┐ │ │
|
||||||
│ │ │ Strip │→ │ WAF │→ │ Auth │ │ │
|
│ │ │ Strip │→ │ Reverse │ │ │
|
||||||
│ │ │ Prefix │ │ Filter │ │ Middleware │ │ │
|
│ │ │ Prefix │ │ Proxy │ │ │
|
||||||
│ │ └────────────┘ └─────────┘ └──────────────┘ │ │
|
│ │ └────────────┘ └──────────────┘ │ │
|
||||||
│ └──────────────────────────────────────────────────────┘ │
|
│ └──────────────────────────────────────────────────────┘ │
|
||||||
└─────────────────────────┬───────────────────────────────────┘
|
└─────────────────────────┬──────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
┌────────────────────────────────────────────────────────────┐
|
||||||
│ Reverse Proxy (httputil.ReverseProxy) │
|
│ Reverse Proxy (httputil.ReverseProxy) │
|
||||||
│ │ │
|
│ │ │
|
||||||
│ ▼ │
|
│ ▼ │
|
||||||
│ Backend Service │
|
│ Backend Service │
|
||||||
└─────────────────────────────────────────────────────────────┘
|
└────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
## Component Architecture
|
## Component Architecture
|
||||||
@@ -51,18 +51,17 @@ app/
|
|||||||
├── config/ # Configuration management
|
├── config/ # Configuration management
|
||||||
│ ├── config.go # Config interface
|
│ ├── config.go # Config interface
|
||||||
│ ├── file.go # File-based config loader
|
│ ├── file.go # File-based config loader
|
||||||
│ └── types.go # Configuration type definitions
|
│ └── database.go # Database configuration
|
||||||
├── server/ # Core server components
|
├── server/ # Core server components
|
||||||
│ ├── gateway.go # Main gateway server
|
│ ├── gateway.go # Main gateway server
|
||||||
│ ├── routes.go # Route handler creation
|
│ ├── routes.go # Route registration
|
||||||
│ └── proxy.go # Host-based virtual hosting
|
│ ├── api.go # API definitions
|
||||||
|
│ ├── host.go # Host definitions
|
||||||
|
│ └── target.go # Target (backend) definitions
|
||||||
├── middlewares/ # HTTP middleware
|
├── middlewares/ # HTTP middleware
|
||||||
│ ├── auth.go # Authentication middleware
|
│ ├── host.go # Host logging middleware
|
||||||
│ └── waf.go # Web Application Firewall
|
│ └── logger.go # Structured logging middleware
|
||||||
├── handlers/ # Request handlers
|
└── utils/ # Utility functions
|
||||||
│ └── route.go # Route handlers (placeholder)
|
|
||||||
└── res/ # HTTP responses
|
|
||||||
└── error.go # Error response utilities
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Core Components
|
### Core Components
|
||||||
@@ -71,25 +70,39 @@ app/
|
|||||||
|
|
||||||
The Gateway is the main server component that:
|
The Gateway is the main server component that:
|
||||||
- Initializes the chi router
|
- Initializes the chi router
|
||||||
- Applies global middleware (request_id, real_ip, logger)
|
- Applies global middleware (request_id, real_ip, logger, host)
|
||||||
|
- Configures proxy directors for each API
|
||||||
- Registers route handlers
|
- Registers route handlers
|
||||||
- Starts the HTTP server
|
- Starts the HTTP server
|
||||||
|
|
||||||
#### Routes (`server/routes.go`)
|
#### Routes (`server/routes.go`)
|
||||||
|
|
||||||
The Routes component creates handlers for each configured route:
|
The Routes component handles:
|
||||||
1. Finds the matching API backend target
|
- Creating route handlers from configuration
|
||||||
2. Creates a reverse proxy using `httputil.NewSingleHostReverseProxy`
|
- Applying strip prefix middleware
|
||||||
3. Optionally strips prefix from the request path
|
- Registering routes with chi router (method-agnostic)
|
||||||
4. Applies middleware chain: WAF → Auth
|
- Connecting routes to API backends
|
||||||
|
|
||||||
#### Configuration (`config/`)
|
#### API (`server/api.go`)
|
||||||
|
|
||||||
Configuration is loaded from YAML and provides:
|
API definitions that:
|
||||||
- Gateway settings (host, port, features)
|
- Link hosts to backend targets
|
||||||
- Route definitions with security policies
|
- Implement `http.Handler` interface for proxying
|
||||||
- API backend targets
|
- Delegate requests to the reverse proxy
|
||||||
- Proxy configurations for virtual hosting
|
|
||||||
|
#### Hosts (`server/host.go`)
|
||||||
|
|
||||||
|
Host definitions for:
|
||||||
|
- Virtual hosting support
|
||||||
|
- Domain-based routing
|
||||||
|
- Host header validation
|
||||||
|
|
||||||
|
#### Targets (`server/target.go`)
|
||||||
|
|
||||||
|
Target (backend) definitions that:
|
||||||
|
- Store backend service URLs
|
||||||
|
- Create `httputil.ReverseProxy` instances
|
||||||
|
- Handle proxy configuration
|
||||||
|
|
||||||
## Middleware Chain
|
## Middleware Chain
|
||||||
|
|
||||||
@@ -100,56 +113,56 @@ Applied to all requests via chi middleware:
|
|||||||
| Feature | Description |
|
| Feature | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `request_id` | Adds unique request ID to context |
|
| `request_id` | Adds unique request ID to context |
|
||||||
| `real_ip` | Determines the real client IP |
|
| `real_ip` | Determines the real client IP from headers |
|
||||||
| `logger` | Logs HTTP requests |
|
| `logger` | Logs HTTP requests with structured JSON output |
|
||||||
|
| `host` | Logs the host header for each request |
|
||||||
|
|
||||||
### Per-Route Middleware
|
### Per-Route Middleware
|
||||||
|
|
||||||
Applied in order to each route handler:
|
Applied to each route handler:
|
||||||
|
|
||||||
1. **StripPrefix** - Removes specified prefix from request path before proxying
|
1. **StripPrefix** - Removes specified prefix from request path before proxying
|
||||||
2. **WAF** - Filters requests based on HTTP method
|
|
||||||
3. **Auth** - Validates authentication credentials
|
|
||||||
|
|
||||||
## Request Flow
|
## Request Flow
|
||||||
|
|
||||||
1. **Client Request** → Gateway receives HTTP request
|
1. **Client Request** → Gateway receives HTTP request
|
||||||
2. **Global Middleware** → Request ID, Real IP, Logging applied
|
2. **Global Middleware** → Request ID, Real IP, Host logging, Logger applied
|
||||||
3. **Route Matching** → Chi matches route pattern (e.g., `/api/v1/dev/*`)
|
3. **Route Matching** → Chi matches route pattern (e.g., `/api/v1/*`)
|
||||||
4. **Per-Route Middleware** → StripPrefix → WAF → Auth
|
4. **Per-Route Middleware** → StripPrefix (if enabled)
|
||||||
5. **Reverse Proxy** → Request forwarded to backend API
|
5. **Reverse Proxy** → Request forwarded to backend API
|
||||||
6. **Response** → Backend response returned to client
|
6. **Response** → Backend response returned to client
|
||||||
|
|
||||||
## Authentication Flow
|
|
||||||
|
|
||||||
The authentication middleware supports path-based filtering:
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────┐
|
|
||||||
│ Include Set? │
|
|
||||||
└──────────┬──────────┘
|
|
||||||
│
|
|
||||||
┌─────┴─────┐
|
|
||||||
│ Yes │ No
|
|
||||||
▼ ▼
|
|
||||||
┌─────────┐ ┌─────────────┐
|
|
||||||
│ Match │ │ Exclude │
|
|
||||||
│ Include?│ │ Set? │
|
|
||||||
└────┬────┘ └──────┬──────┘
|
|
||||||
│ │
|
|
||||||
┌──┴──┐ ┌──┴──┐
|
|
||||||
│Yes │No │Yes │No
|
|
||||||
▼ ▼ ▼ ▼
|
|
||||||
┌────┐┌────┐ ┌────┐┌────┐
|
|
||||||
│Auth││Skip│ │Skip││Auth│
|
|
||||||
└────┘└────┘ └────┘└────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration Flow
|
## Configuration Flow
|
||||||
|
|
||||||
1. Load `gateway.yaml` via `config.NewFileConfig()`
|
1. Load `gateway.yaml` via `config.NewFile()`
|
||||||
2. Parse YAML into `Configuration` struct
|
2. Parse YAML into `Configuration` struct
|
||||||
3. Create Gateway with configuration
|
3. Create Hosts from configuration
|
||||||
4. Create Routes from route definitions and API targets
|
4. Create Targets from configuration
|
||||||
5. Register handlers with chi router
|
5. Create APIs (linking Hosts to Targets)
|
||||||
6. Start HTTP server
|
6. Create Routes (linking Routes to APIs)
|
||||||
|
7. Initialize Gateway with all components
|
||||||
|
8. Configure proxy directors
|
||||||
|
9. Register routes with chi router
|
||||||
|
10. Start HTTP server
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
The gateway uses structured JSON logging via `masterlog`:
|
||||||
|
|
||||||
|
- **HTTP Request Logging** - method, path, status, duration, host, IP
|
||||||
|
- **Gateway Events** - startup, route registration, proxy configuration
|
||||||
|
- **Sensitive Field Pseudonymization** - user_id, email, ip fields are pseudonymized
|
||||||
|
|
||||||
|
Example log output:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"level": "info",
|
||||||
|
"msg": "HTTP Request",
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/v1/users",
|
||||||
|
"status": 200,
|
||||||
|
"duration": "45ms",
|
||||||
|
"host": "localhost:8080",
|
||||||
|
"ip": "127.0.0.1:52342"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|||||||
@@ -12,33 +12,30 @@ gateway:
|
|||||||
- request_id
|
- request_id
|
||||||
- real_ip
|
- real_ip
|
||||||
- logger
|
- logger
|
||||||
|
- host
|
||||||
|
|
||||||
proxies:
|
hosts:
|
||||||
- id: "proxy-id"
|
- id: "host-001"
|
||||||
host: "example.com"
|
name: "localhost"
|
||||||
target: "http://backend:3000"
|
domain: "localhost:8080"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "httpbin"
|
||||||
|
url: "https://httpbin.org"
|
||||||
|
|
||||||
apis:
|
apis:
|
||||||
- id: "api-id"
|
- id: "api-001"
|
||||||
target: "https://api.example.com"
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- id: "route-id"
|
- id: "route-001"
|
||||||
|
api: "api-001"
|
||||||
path: "/api/v1/*"
|
path: "/api/v1/*"
|
||||||
strip_prefix:
|
strip_prefix:
|
||||||
enabled: true
|
enabled: true
|
||||||
prefix: "/api/v1"
|
prefix: "/api/v1"
|
||||||
security:
|
|
||||||
auth:
|
|
||||||
enabled: true
|
|
||||||
type: "api_key"
|
|
||||||
header: "X-Api-Key"
|
|
||||||
path:
|
|
||||||
include: []
|
|
||||||
exclude: []
|
|
||||||
waf:
|
|
||||||
enabled: true
|
|
||||||
methods: ["GET", "POST"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Sections
|
## Sections
|
||||||
@@ -61,37 +58,49 @@ Available global features:
|
|||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `request_id` | Adds unique request ID to each request |
|
| `request_id` | Adds unique request ID to each request |
|
||||||
| `real_ip` | Determines real client IP from headers |
|
| `real_ip` | Determines real client IP from headers |
|
||||||
| `logger` | Logs all HTTP requests |
|
| `logger` | Logs all HTTP requests with structured JSON |
|
||||||
|
| `host` | Logs the host header for each request |
|
||||||
|
|
||||||
### Proxies
|
### Hosts
|
||||||
|
|
||||||
Virtual hosting configuration for host-based routing.
|
Virtual hosting configuration for domain-based routing.
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `id` | string | Unique proxy identifier |
|
| `id` | string | Unique host identifier (referenced by APIs) |
|
||||||
| `host` | string | Domain/host name to match |
|
| `name` | string | Human-readable name |
|
||||||
| `target` | string | Backend URL to proxy to |
|
| `domain` | string | Domain/host name to match |
|
||||||
|
|
||||||
|
### Targets
|
||||||
|
|
||||||
|
Backend service definitions referenced by APIs.
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `id` | string | Unique target identifier (referenced by APIs) |
|
||||||
|
| `name` | string | Human-readable name |
|
||||||
|
| `url` | string | Backend URL to proxy to |
|
||||||
|
|
||||||
### APIs
|
### APIs
|
||||||
|
|
||||||
Backend service definitions referenced by routes.
|
Links hosts to backend targets.
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `id` | string | Unique API identifier (referenced by routes) |
|
| `id` | string | Unique API identifier (referenced by routes) |
|
||||||
| `target` | string | Backend URL |
|
| `host` | string | Host ID to use |
|
||||||
|
| `target` | string | Target ID to proxy to |
|
||||||
|
|
||||||
### Routes
|
### Routes
|
||||||
|
|
||||||
Route definitions with security policies.
|
Route definitions with path patterns and prefix stripping.
|
||||||
|
|
||||||
| Field | Type | Description |
|
| Field | Type | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
| `id` | string | Unique route identifier (must match API ID) |
|
| `id` | string | Unique route identifier |
|
||||||
|
| `api` | string | API ID to use for this route |
|
||||||
| `path` | string | Chi route pattern (e.g., `/api/v1/*`) |
|
| `path` | string | Chi route pattern (e.g., `/api/v1/*`) |
|
||||||
| `strip_prefix` | object | Prefix stripping configuration |
|
| `strip_prefix` | object | Prefix stripping configuration |
|
||||||
| `security` | object | Security policies (auth, WAF) |
|
|
||||||
|
|
||||||
#### Strip Prefix
|
#### Strip Prefix
|
||||||
|
|
||||||
@@ -100,91 +109,112 @@ Route definitions with security policies.
|
|||||||
| `enabled` | boolean | Enable prefix stripping |
|
| `enabled` | boolean | Enable prefix stripping |
|
||||||
| `prefix` | string | Prefix to remove from path |
|
| `prefix` | string | Prefix to remove from path |
|
||||||
|
|
||||||
#### Security
|
|
||||||
|
|
||||||
##### Authentication
|
|
||||||
|
|
||||||
| Field | Type | Description |
|
|
||||||
|-------|------|-------------|
|
|
||||||
| `enabled` | boolean | Enable authentication |
|
|
||||||
| `type` | string | Auth type (`api_key`, `session`, etc.) |
|
|
||||||
| `header` | string | Header name to validate |
|
|
||||||
| `path` | object | Path-based filtering |
|
|
||||||
|
|
||||||
##### Auth Path Filtering
|
|
||||||
|
|
||||||
| Field | Type | Description |
|
|
||||||
|-------|------|-------------|
|
|
||||||
| `include` | array | Paths that require auth (empty = all) |
|
|
||||||
| `exclude` | array | Paths that skip auth |
|
|
||||||
|
|
||||||
**Include/Exclude Logic:**
|
|
||||||
- If `include` is set → only matching paths require auth
|
|
||||||
- If `include` is empty → all paths require auth except `exclude`
|
|
||||||
|
|
||||||
Wildcards (`*`) are supported in path patterns.
|
|
||||||
|
|
||||||
##### WAF (Web Application Firewall)
|
|
||||||
|
|
||||||
| Field | Type | Description |
|
|
||||||
|-------|------|-------------|
|
|
||||||
| `enabled` | boolean | Enable WAF |
|
|
||||||
| `methods` | array | Allowed HTTP methods (`["*"]` for all) |
|
|
||||||
|
|
||||||
## Example Configurations
|
## Example Configurations
|
||||||
|
|
||||||
### Public API (No Auth)
|
### Simple Proxy (No Prefix Stripping)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
gateway:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
features:
|
||||||
|
- logger
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
- id: "host-001"
|
||||||
|
name: "localhost"
|
||||||
|
domain: "localhost:8080"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "backend"
|
||||||
|
url: "https://api.example.com"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "api-001"
|
||||||
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- id: "public-api"
|
- id: "route-001"
|
||||||
path: "/public/*"
|
api: "api-001"
|
||||||
strip_prefix:
|
path: "/api/*"
|
||||||
enabled: true
|
|
||||||
prefix: "/public"
|
|
||||||
security:
|
|
||||||
auth:
|
|
||||||
enabled: false
|
|
||||||
waf:
|
|
||||||
enabled: true
|
|
||||||
methods: ["GET", "POST"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Protected API with API Key
|
**Request flow:**
|
||||||
|
- Client requests: `/api/users/123`
|
||||||
|
- Backend receives: `/api/users/123`
|
||||||
|
|
||||||
|
### Prefix Stripping
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
routes:
|
routes:
|
||||||
- id: "protected-api"
|
- id: "route-001"
|
||||||
|
api: "api-001"
|
||||||
path: "/api/v1/*"
|
path: "/api/v1/*"
|
||||||
strip_prefix:
|
strip_prefix:
|
||||||
enabled: true
|
enabled: true
|
||||||
prefix: "/api/v1"
|
prefix: "/api/v1"
|
||||||
security:
|
|
||||||
auth:
|
|
||||||
enabled: true
|
|
||||||
type: "api_key"
|
|
||||||
header: "X-Api-Key"
|
|
||||||
waf:
|
|
||||||
enabled: true
|
|
||||||
methods: ["*"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mixed Auth (Path-based)
|
**Request flow:**
|
||||||
|
- Client requests: `/api/v1/users/123`
|
||||||
|
- Gateway strips: `/api/v1`
|
||||||
|
- Backend receives: `/users/123`
|
||||||
|
|
||||||
|
### Multiple Routes
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
routes:
|
routes:
|
||||||
- id: "mixed-api"
|
- id: "public-route"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/public/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/public"
|
||||||
|
|
||||||
|
- id: "api-route"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/api/v1/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/api/v1"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple Backends
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
hosts:
|
||||||
|
- id: "host-001"
|
||||||
|
name: "api-host"
|
||||||
|
domain: "api.example.com"
|
||||||
|
- id: "host-002"
|
||||||
|
name: "admin-host"
|
||||||
|
domain: "admin.example.com"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "api-backend"
|
||||||
|
url: "https://api-backend.internal"
|
||||||
|
- id: "target-002"
|
||||||
|
name: "admin-backend"
|
||||||
|
url: "https://admin-backend.internal"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "api-001"
|
||||||
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
- id: "api-002"
|
||||||
|
host: "host-002"
|
||||||
|
target: "target-002"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- id: "route-001"
|
||||||
|
api: "api-001"
|
||||||
path: "/api/*"
|
path: "/api/*"
|
||||||
security:
|
- id: "route-002"
|
||||||
auth:
|
api: "api-002"
|
||||||
enabled: true
|
path: "/admin/*"
|
||||||
header: "Authorization"
|
|
||||||
path:
|
|
||||||
include: ["/api/admin/*", "/api/users/*/profile"]
|
|
||||||
exclude: ["/api/health", "/api/public/*"]
|
|
||||||
waf:
|
|
||||||
enabled: true
|
|
||||||
methods: ["*"]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration Loading
|
## Configuration Loading
|
||||||
@@ -192,7 +222,7 @@ routes:
|
|||||||
The gateway loads configuration from a file path relative to the binary:
|
The gateway loads configuration from a file path relative to the binary:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
cfg, err := config.NewFileConfig("../gateway.yaml")
|
cfg, err := config.NewFile("../gateway.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
For Docker deployments, mount the config file:
|
For Docker deployments, mount the config file:
|
||||||
@@ -201,3 +231,16 @@ For Docker deployments, mount the config file:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./gateway.yaml:/app/gateway.yaml:ro
|
- ./gateway.yaml:/app/gateway.yaml:ro
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Chi Route Patterns
|
||||||
|
|
||||||
|
The gateway uses chi/v5 routing patterns. Common patterns:
|
||||||
|
|
||||||
|
| Pattern | Matches | Example |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| `/api/*` | `/api/` and any subpath | `/api/users`, `/api/users/123` |
|
||||||
|
| `/api/v1/*` | `/api/v1/` and any subpath | `/api/v1/users` |
|
||||||
|
| `/users/{id}` | `/users/` with any value | `/users/123` |
|
||||||
|
| `/files/*` | `/files/` and any subpath | `/files/doc.pdf` |
|
||||||
|
|
||||||
|
Note: `/*` matches zero or more path segments.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Welcome to the official documentation for the SecNex API Gateway.
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
SecNex API Gateway is a high-performance, configurable API gateway built in Go. It provides reverse proxy capabilities with built-in security features including authentication and web application firewall (WAF) functionality.
|
SecNex API Gateway is a high-performance, configurable API gateway built in Go. It provides reverse proxy capabilities with path-based routing, prefix stripping, and structured logging.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -28,11 +28,11 @@ docker compose up -d
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Reverse Proxy** Route requests to backend services
|
- **Reverse Proxy** Route requests to backend services
|
||||||
- **Authentication** Header-based authentication (API key, session tokens)
|
- **Path-based Routing** Configurable route patterns with chi/v5
|
||||||
- **WAF** Web Application Firewall with method filtering and IP-based access control
|
- **Prefix Stripping** Remove path prefixes before proxying
|
||||||
- **Path-based Routing** Configurable route patterns with prefix stripping
|
- **Host-based Routing** Virtual hosting support
|
||||||
- **Middleware Pipeline** Extensible middleware chain for custom logic
|
- **Middleware Pipeline** Extensible middleware chain (request ID, real IP, logging)
|
||||||
- **Logging** Structured logging with sensitive field pseudonymization
|
- **Logging** Structured JSON logging with sensitive field pseudonymization
|
||||||
|
|
||||||
## Health Check
|
## Health Check
|
||||||
|
|
||||||
|
|||||||
190
.docs/usage.md
190
.docs/usage.md
@@ -47,14 +47,13 @@ Response: `OK`
|
|||||||
After configuring routes in `gateway.yaml`, make requests to the gateway:
|
After configuring routes in `gateway.yaml`, make requests to the gateway:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Example: Request to a route configured at /api/v1/dev/*
|
# Example: Request to a route configured at /api/v1/*
|
||||||
curl http://localhost:8080/api/v1/dev/users
|
curl http://localhost:8080/api/v1/users
|
||||||
|
|
||||||
# With API key authentication
|
# All HTTP methods are supported
|
||||||
curl -H "X-Api-Key: your-key-here" http://localhost:8080/api/v1/dev/data
|
curl -X POST http://localhost:8080/api/v1/data
|
||||||
|
curl -X PUT http://localhost:8080/api/v1/data/123
|
||||||
# With session authentication
|
curl -X DELETE http://localhost:8080/api/v1/data/123
|
||||||
curl -H "Authorization: Bearer token" http://localhost:8080/api/v1/protected
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Route Examples
|
## Route Examples
|
||||||
@@ -65,6 +64,7 @@ curl -H "Authorization: Bearer token" http://localhost:8080/api/v1/protected
|
|||||||
```yaml
|
```yaml
|
||||||
routes:
|
routes:
|
||||||
- id: "api"
|
- id: "api"
|
||||||
|
api: "api-001"
|
||||||
path: "/api/v1/*"
|
path: "/api/v1/*"
|
||||||
strip_prefix:
|
strip_prefix:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -76,65 +76,57 @@ routes:
|
|||||||
- Gateway strips: `/api/v1`
|
- Gateway strips: `/api/v1`
|
||||||
- Backend receives: `/users/123`
|
- Backend receives: `/users/123`
|
||||||
|
|
||||||
### Authentication Example
|
### Multiple Routes Example
|
||||||
|
|
||||||
**Configuration:**
|
**Configuration:**
|
||||||
```yaml
|
```yaml
|
||||||
security:
|
routes:
|
||||||
auth:
|
- id: "public-route"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/public/*"
|
||||||
|
strip_prefix:
|
||||||
enabled: true
|
enabled: true
|
||||||
type: "api_key"
|
prefix: "/public"
|
||||||
header: "X-Api-Key"
|
|
||||||
```
|
|
||||||
|
|
||||||
**Valid request:**
|
- id: "api-route"
|
||||||
```bash
|
api: "api-001"
|
||||||
curl -H "X-Api-Key: secret123" http://localhost:8080/api/v1/data
|
path: "/api/v1/*"
|
||||||
```
|
strip_prefix:
|
||||||
|
|
||||||
**Invalid request (missing header):**
|
|
||||||
```bash
|
|
||||||
curl http://localhost:8080/api/v1/data
|
|
||||||
# Returns: 401 Unauthorized
|
|
||||||
```
|
|
||||||
|
|
||||||
### WAF Method Filtering Example
|
|
||||||
|
|
||||||
**Configuration:**
|
|
||||||
```yaml
|
|
||||||
security:
|
|
||||||
waf:
|
|
||||||
enabled: true
|
enabled: true
|
||||||
methods: ["GET", "POST"]
|
prefix: "/api/v1"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Allowed:**
|
**Requests:**
|
||||||
```bash
|
```bash
|
||||||
curl -X GET http://localhost:8080/api/v1/data
|
# Public route - backend receives /status
|
||||||
curl -X POST http://localhost:8080/api/v1/data
|
curl http://localhost:8080/public/status
|
||||||
```
|
|
||||||
|
|
||||||
**Blocked:**
|
# API route - backend receives /users
|
||||||
```bash
|
curl http://localhost:8080/api/v1/users
|
||||||
curl -X DELETE http://localhost:8080/api/v1/data
|
|
||||||
# Returns: 403 Forbidden
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Logging
|
## Logging
|
||||||
|
|
||||||
The gateway uses structured logging via `masterlog`. Logs include:
|
The gateway uses structured JSON logging via `masterlog`. All HTTP requests are logged with:
|
||||||
|
|
||||||
- Request ID (if enabled)
|
- Request ID (if enabled)
|
||||||
- Client IP (if real_ip enabled)
|
- Client IP (if real_ip enabled)
|
||||||
- Request method and path
|
- Request method and path
|
||||||
- Response status
|
- Response status code
|
||||||
|
- Request duration
|
||||||
|
- Host header
|
||||||
|
|
||||||
**Example log output:**
|
**Example log output:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"level": "info",
|
"level": "info",
|
||||||
"msg": "Registering route",
|
"msg": "HTTP Request",
|
||||||
"path": "/api/v1/dev/*"
|
"method": "GET",
|
||||||
|
"path": "/api/v1/users",
|
||||||
|
"status": 200,
|
||||||
|
"duration": "45ms",
|
||||||
|
"host": "localhost:8080",
|
||||||
|
"ip": "127.0.0.1:52342"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -147,30 +139,116 @@ The gateway uses structured logging via `masterlog`. Logs include:
|
|||||||
lsof -i :8080
|
lsof -i :8080
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Verify configuration file exists and is valid YAML
|
2. Verify configuration file exists and is valid YAML:
|
||||||
|
```bash
|
||||||
|
cat ../gateway.yaml
|
||||||
|
```
|
||||||
|
|
||||||
3. Check logs for detailed error messages
|
3. Check logs for detailed error messages
|
||||||
|
|
||||||
### 401 Unauthorized
|
### 404 Not Found
|
||||||
|
|
||||||
- Verify auth header is included
|
- Verify the route path matches your request
|
||||||
- Check header name matches configuration
|
- Check chi route pattern syntax (use `/*` for wildcards)
|
||||||
- Verify path is not excluded from auth
|
- Ensure the route is registered (check startup logs)
|
||||||
|
|
||||||
### 403 Forbidden
|
|
||||||
|
|
||||||
- Check WAF method configuration
|
|
||||||
- Verify HTTP method is allowed
|
|
||||||
|
|
||||||
### Backend connection errors
|
### Backend connection errors
|
||||||
|
|
||||||
- Verify API target URL is correct
|
- Verify target URL is correct in configuration
|
||||||
- Check backend service is running
|
- Check backend service is running and accessible
|
||||||
- Verify network connectivity
|
- Verify network connectivity from gateway to backend
|
||||||
|
- Check DNS resolution if using domain names
|
||||||
|
|
||||||
|
### Route not matching
|
||||||
|
|
||||||
|
- Ensure request path matches the route pattern exactly
|
||||||
|
- Remember that `/*` matches zero or more path segments
|
||||||
|
- Check that multiple routes don't have conflicting patterns
|
||||||
|
|
||||||
## Performance Considerations
|
## Performance Considerations
|
||||||
|
|
||||||
- The gateway uses Go's `httputil.ReverseProxy` for efficient proxying
|
- The gateway uses Go's `httputil.ReverseProxy` for efficient proxying
|
||||||
|
- HTTP/2 is supported when both client and backend support it
|
||||||
- Keep-alive connections are reused by default
|
- Keep-alive connections are reused by default
|
||||||
- Consider connection pooling for high-traffic scenarios
|
- Consider connection pooling for high-traffic scenarios
|
||||||
- Monitor memory usage with high request volumes
|
- Monitor memory usage with high request volumes
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### API Versioning
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
routes:
|
||||||
|
- id: "v1-api"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/api/v1/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/api/v1"
|
||||||
|
|
||||||
|
- id: "v2-api"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/api/v2/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/api/v2"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Microservices Routing
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
targets:
|
||||||
|
- id: "user-service"
|
||||||
|
name: "User Service"
|
||||||
|
url: "https://user-service.internal"
|
||||||
|
- id: "order-service"
|
||||||
|
name: "Order Service"
|
||||||
|
url: "https://order-service.internal"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "user-api"
|
||||||
|
host: "host-001"
|
||||||
|
target: "user-service"
|
||||||
|
- id: "order-api"
|
||||||
|
host: "host-001"
|
||||||
|
target: "order-service"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- id: "users-route"
|
||||||
|
api: "user-api"
|
||||||
|
path: "/users/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/users"
|
||||||
|
|
||||||
|
- id: "orders-route"
|
||||||
|
api: "order-api"
|
||||||
|
path: "/orders/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/orders"
|
||||||
|
```
|
||||||
|
|
||||||
|
### External API Proxy
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
targets:
|
||||||
|
- id: "external-api"
|
||||||
|
name: "External API"
|
||||||
|
url: "https://api.external.com"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "external"
|
||||||
|
host: "host-001"
|
||||||
|
target: "external-api"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- id: "external-proxy"
|
||||||
|
api: "external"
|
||||||
|
path: "/proxy/external/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/proxy/external"
|
||||||
|
```
|
||||||
|
|
||||||
|
Request to `/proxy/external/users` becomes `/users` on the external API.
|
||||||
|
|||||||
129
CLAUDE.md
129
CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
SecNex API Gateway is a Go-based API gateway built with chi/v5 routing. It acts as a reverse proxy with configurable security features including authentication and WAF (Web Application Firewall) capabilities.
|
SecNex API Gateway is a Go-based API gateway built with chi/v5 routing. It acts as a reverse proxy with configurable features including path-based routing, prefix stripping, and structured logging.
|
||||||
|
|
||||||
## Build and Run
|
## Build and Run
|
||||||
|
|
||||||
@@ -23,77 +23,79 @@ The gateway loads configuration from `gateway.yaml` (sibling to the `app/` direc
|
|||||||
app/
|
app/
|
||||||
├── main.go # Entry point
|
├── main.go # Entry point
|
||||||
├── config/ # Configuration loading and types
|
├── config/ # Configuration loading and types
|
||||||
├── server/ # Gateway, routes, and proxy setup
|
├── server/ # Gateway, routes, hosts, targets, and API definitions
|
||||||
├── middlewares/ # Auth and WAF middleware
|
├── middlewares/ # HTTP middleware (logger, host)
|
||||||
├── handlers/ # Route handlers (currently empty)
|
└── utils/ # Utility functions
|
||||||
└── res/ # HTTP error responses
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Core Components
|
### Core Components
|
||||||
|
|
||||||
**Gateway (`server/gateway.go`)**
|
**Gateway (`server/gateway.go`)**
|
||||||
- Main server using chi/v5 router
|
- Main server using chi/v5 router
|
||||||
- Dynamically enables features via config: `request_id`, `real_ip`, `logger`
|
- Dynamically enables features via config: `request_id`, `real_ip`, `logger`, `host`
|
||||||
|
- Configures proxy directors for each API
|
||||||
- Registers route handlers and starts HTTP server
|
- Registers route handlers and starts HTTP server
|
||||||
|
|
||||||
**Routes (`server/routes.go`)**
|
**Routes (`server/routes.go`)**
|
||||||
- Creates handlers for each route configured in `gateway.yaml`
|
- Creates handlers for each route configured in `gateway.yaml`
|
||||||
- For each route:
|
- For each route:
|
||||||
1. Finds the matching API backend target
|
1. Finds the matching API backend target
|
||||||
2. Creates a reverse proxy using `httputil.NewSingleHostReverseProxy`
|
2. Creates a handler with optional strip prefix middleware
|
||||||
3. Optionally strips prefix from the request path
|
3. Registers with chi router using `r.Handle()` (method-agnostic)
|
||||||
4. Applies WAF middleware (method filtering)
|
|
||||||
5. Applies Auth middleware (header-based authentication)
|
|
||||||
|
|
||||||
**Proxy (`server/proxy.go`)**
|
**API (`server/api.go`)**
|
||||||
- Host-based virtual hosting proxy (separate from routes)
|
- Links hosts to backend targets
|
||||||
- Maps `proxy.host` to a backend target
|
- Implements `http.Handler` interface
|
||||||
- Currently unused in main.go but available
|
- Delegates to the reverse proxy
|
||||||
|
|
||||||
**Configuration Flow**
|
**Hosts (`server/host.go`)**
|
||||||
1. `config.NewFileConfig("../gateway.yaml")` loads YAML
|
- Host definitions for virtual hosting
|
||||||
|
- Domain-based routing support
|
||||||
|
|
||||||
|
**Targets (`server/target.go`)**
|
||||||
|
- Backend service definitions
|
||||||
|
- Creates `httputil.NewSingleHostReverseProxy` instances
|
||||||
|
|
||||||
|
### Configuration Flow
|
||||||
|
|
||||||
|
1. `config.NewFile("../gateway.yaml")` loads YAML
|
||||||
2. `server.NewGateway(cfg)` creates gateway with chi router
|
2. `server.NewGateway(cfg)` creates gateway with chi router
|
||||||
3. `server.NewRoutes(cfg.GetRoutes(), cfg.GetApis())` creates handlers
|
3. `server.NewRoutes(cfg, apis)` creates route handlers
|
||||||
4. `gateway.SetRoutes(routes)` registers handlers
|
4. `routes.Register(g.router)` registers handlers
|
||||||
|
5. Gateway starts HTTP server
|
||||||
|
|
||||||
### Middleware Chain (per route)
|
### Middleware Chain
|
||||||
|
|
||||||
Middlewares are applied in order via decorator pattern in `server/routes.go:createHandlers`:
|
**Global Middleware** (applied via chi middleware):
|
||||||
1. StripPrefix (if enabled) - removes prefix from path before proxying
|
1. RequestID - adds unique request ID
|
||||||
2. WAF - filters by HTTP method (or `["*"]` for all methods)
|
2. RealIP - determines real client IP
|
||||||
3. Auth - validates presence of auth header
|
3. Logger - structured JSON logging
|
||||||
|
4. Host - logs host header
|
||||||
|
|
||||||
|
**Per-Route Middleware** (applied in order):
|
||||||
|
1. StripPrefix - removes prefix from path before proxying (if enabled)
|
||||||
|
|
||||||
### Key Implementation Details
|
### Key Implementation Details
|
||||||
|
|
||||||
**Auth Middleware** (`middlewares/auth.go`)
|
**Strip Prefix Middleware** (`server/routes.go`)
|
||||||
- Checks for presence of configured header (e.g., `X-Api-Key`, `Authorization`)
|
- Removes specified prefix from request path before proxying
|
||||||
- Path-based filtering via `include`/`exclude` patterns:
|
- Ensures resulting path starts with `/`
|
||||||
- If `include` is set → only those paths require auth
|
|
||||||
- If `include` is empty → all paths require auth except `exclude` patterns
|
|
||||||
- Supports wildcard patterns (`*`) in path matching
|
|
||||||
- Deletes the auth header before forwarding to backend
|
|
||||||
|
|
||||||
**WAF Configuration** (`middlewares/waf.go`)
|
|
||||||
- Currently only implements HTTP method filtering
|
|
||||||
- `methods: ["*"]` allows all methods
|
|
||||||
- `methods: ["GET"]` only allows GET
|
|
||||||
|
|
||||||
**Route Handler Pattern**
|
**Route Handler Pattern**
|
||||||
Each route in `gateway.yaml` must have:
|
Each route in `gateway.yaml` must have:
|
||||||
- `id` - must match an API entry
|
- `id` - unique route identifier
|
||||||
- `path` - chi route pattern (e.g., `/api/v1/dev/*`)
|
- `api` - API ID to use (references an API entry)
|
||||||
|
- `path` - chi route pattern (e.g., `/api/v1/*`)
|
||||||
- `strip_prefix` - optional prefix removal
|
- `strip_prefix` - optional prefix removal
|
||||||
- `security.auth` - optional auth middleware
|
|
||||||
- `security.waf` - optional method filtering
|
|
||||||
|
|
||||||
### Module Structure
|
### Module Structure
|
||||||
|
|
||||||
The codebase uses an internal Go module:
|
The codebase uses an internal Go module:
|
||||||
```
|
```
|
||||||
git.secnex.io/secnex/gateway
|
git.secnex.io/secnex/api-gateway
|
||||||
```
|
```
|
||||||
|
|
||||||
Internal imports use this path (e.g., `git.secnex.io/secnex/gateway/config`).
|
Internal imports use this path (e.g., `git.secnex.io/secnex/api-gateway/config`).
|
||||||
|
|
||||||
### Logging
|
### Logging
|
||||||
|
|
||||||
@@ -101,3 +103,48 @@ Uses `git.secnex.io/secnex/masterlog` with:
|
|||||||
- JSON encoder
|
- JSON encoder
|
||||||
- Pseudonymizer for sensitive fields (`user_id`, `email`, `ip`)
|
- Pseudonymizer for sensitive fields (`user_id`, `email`, `ip`)
|
||||||
- Debug-level logging enabled in main.go
|
- Debug-level logging enabled in main.go
|
||||||
|
- Custom `LoggerMiddleware` for structured HTTP request logging
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
- `github.com/go-chi/chi/v5` - HTTP router
|
||||||
|
- `git.secnex.io/secnex/masterlog` - Structured logging
|
||||||
|
- `go.yaml.in/yaml/v3` - YAML configuration parsing
|
||||||
|
- `gorm.io/gorm` - Database ORM (for future use)
|
||||||
|
- `gorm.io/driver/postgres` - PostgreSQL driver (for future use)
|
||||||
|
|
||||||
|
## Configuration Reference
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
gateway:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
features:
|
||||||
|
- request_id
|
||||||
|
- real_ip
|
||||||
|
- logger
|
||||||
|
- host
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
- id: "host-001"
|
||||||
|
name: "localhost"
|
||||||
|
domain: "localhost:8080"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "httpbin"
|
||||||
|
url: "https://httpbin.org"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "api-001"
|
||||||
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- id: "route-001"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/api/v1/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/api/v1"
|
||||||
|
```
|
||||||
|
|||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 SecNex GmbH
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
103
README.md
103
README.md
@@ -1 +1,104 @@
|
|||||||
# SecNex API Gateway
|
# SecNex API Gateway
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
A high-performance, configurable API gateway built in Go with chi/v5 routing. Provides reverse proxy capabilities with path-based routing, prefix stripping, and structured logging.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Reverse Proxy** - Route requests to backend services via HTTP reverse proxy
|
||||||
|
- **Path-based Routing** - Configurable route patterns with chi/v5 router
|
||||||
|
- **Prefix Stripping** - Remove path prefixes before forwarding to backends
|
||||||
|
- **Host-based Routing** - Virtual hosting support via host headers
|
||||||
|
- **Middleware Pipeline** - Extensible middleware chain (request ID, real IP, logging)
|
||||||
|
- **Structured Logging** - JSON logging with sensitive field pseudonymization
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone https://git.secnex.io/secnex/gateway.git
|
||||||
|
cd gateway/app
|
||||||
|
|
||||||
|
# Run the gateway
|
||||||
|
go run main.go
|
||||||
|
```
|
||||||
|
|
||||||
|
The gateway loads configuration from `../gateway.yaml` and starts on the configured host/port (default: `0.0.0.0:8080`).
|
||||||
|
|
||||||
|
## Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:8080/_/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns `200 OK` when the gateway is running.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Documentation](https://git.secnex.io/secnex/gateway/-/tree/main/.docs)
|
||||||
|
- [Architecture](https://git.secnex.io/secnex/gateway/-/blob/main/.docs/architecture.md)
|
||||||
|
- [Configuration](https://git.secnex.io/secnex/gateway/-/blob/main/.docs/configuration.md)
|
||||||
|
- [Usage](https://git.secnex.io/secnex/gateway/-/blob/main/.docs/usage.md)
|
||||||
|
- [Development](https://git.secnex.io/secnex/gateway/-/blob/main/.docs/development.md)
|
||||||
|
- [Deployment](https://git.secnex.io/secnex/gateway/-/blob/main/.docs/deployment.md)
|
||||||
|
|
||||||
|
## Example Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
gateway:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
features:
|
||||||
|
- request_id
|
||||||
|
- real_ip
|
||||||
|
- logger
|
||||||
|
- host
|
||||||
|
|
||||||
|
hosts:
|
||||||
|
- id: "host-001"
|
||||||
|
name: "localhost"
|
||||||
|
domain: "localhost:8080"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "httpbin"
|
||||||
|
url: "https://httpbin.org"
|
||||||
|
|
||||||
|
apis:
|
||||||
|
- id: "api-001"
|
||||||
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
|
||||||
|
routes:
|
||||||
|
- id: "route-001"
|
||||||
|
api: "api-001"
|
||||||
|
path: "/api/v1/*"
|
||||||
|
strip_prefix:
|
||||||
|
enabled: true
|
||||||
|
prefix: "/api/v1"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
├── main.go # Entry point
|
||||||
|
├── config/ # Configuration loading
|
||||||
|
├── server/ # Gateway, routes, proxy
|
||||||
|
├── middlewares/ # HTTP middleware
|
||||||
|
└── utils/ # Utility functions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Go 1.25.5 or later
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Made with ❤️ by [SecNex](https://secnex.io)
|
||||||
|
|||||||
29
gateway.yaml
29
gateway.yaml
@@ -2,25 +2,36 @@ gateway:
|
|||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
port: 8080
|
port: 8080
|
||||||
features:
|
features:
|
||||||
|
- host
|
||||||
- request_id
|
- request_id
|
||||||
- real_ip
|
- real_ip
|
||||||
- logger
|
- logger
|
||||||
|
|
||||||
proxies:
|
hosts:
|
||||||
- id: "proxy-id"
|
- id: "host-001"
|
||||||
host: "example.com"
|
name: "host-001"
|
||||||
target: "http://backend:3000"
|
domain: "localhost:8080"
|
||||||
|
- id: "host-002"
|
||||||
|
name: "host-002"
|
||||||
|
domain: "api.deinserver.co"
|
||||||
|
|
||||||
|
targets:
|
||||||
|
- id: "target-001"
|
||||||
|
name: "target-001"
|
||||||
|
url: "https://httpbin.org"
|
||||||
|
|
||||||
apis:
|
apis:
|
||||||
- id: "api-id"
|
- id: "api-001"
|
||||||
target: "https://api.example.com"
|
host: "host-001"
|
||||||
|
target: "target-001"
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
- id: "route-id"
|
- id: "route-001"
|
||||||
path: "/api/v1/*"
|
api: "api-001"
|
||||||
|
path: "/api/v1/public/*"
|
||||||
strip_prefix:
|
strip_prefix:
|
||||||
enabled: true
|
enabled: true
|
||||||
prefix: "/api/v1"
|
prefix: "/api/v1/public"
|
||||||
security:
|
security:
|
||||||
auth:
|
auth:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|||||||
Reference in New Issue
Block a user