soajs.controller 4.2.41 → 4.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +43 -0
- package/.github/workflows/release.yml +92 -0
- package/ARCHITECTURE.md +193 -0
- package/Gruntfile.js +1 -1
- package/docs/configuration-custom-registry.md +421 -0
- package/docs/configuration-services-config.md +275 -0
- package/docs/data-flow.md +138 -0
- package/docs/deployment.md +205 -0
- package/docs/external-integrations.md +159 -0
- package/docs/gateway-routes.md +259 -0
- package/docs/maintenance-routes.md +308 -0
- package/docs/middleware/awareness.md +120 -0
- package/docs/middleware/cors.md +88 -0
- package/docs/middleware/enhancer.md +75 -0
- package/docs/middleware/favicon.md +36 -0
- package/docs/middleware/gotoService.md +146 -0
- package/docs/middleware/ip2ban.md +70 -0
- package/docs/middleware/key.md +196 -0
- package/docs/middleware/keyACL.md +139 -0
- package/docs/middleware/lastSeen.md +111 -0
- package/docs/middleware/maintenanceMode.md +81 -0
- package/docs/middleware/mt.md +188 -0
- package/docs/middleware/oauth.md +173 -0
- package/docs/middleware/response.md +106 -0
- package/docs/middleware/soajs.md +71 -0
- package/docs/middleware/traffic.md +190 -0
- package/docs/middleware/url.md +102 -0
- package/docs/multi-tenant-security.md +183 -0
- package/docs/request-flow.md +230 -0
- package/docs/service-discovery.md +167 -0
- package/mw/gotoService/redirectToService.js +15 -4
- package/mw/key/index.js +16 -1
- package/mw/lastSeen/index.js +3 -0
- package/mw/mt/urac.js +21 -1
- package/mw/mt/utils.js +2 -0
- package/package.json +7 -7
- package/test/integration/UC1-gateway-routes/index.js +2 -2
- package/test/unit/mw/key/index.js +150 -0
- package/test/unit/mw/lastSeen/index.js +5 -4
- package/test/unit/mw/mt/urac.js +157 -4
- package/test/unit/mw/mt/utils.js +6 -6
- package/.travis.yml +0 -72
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Built-in Gateway Routes
|
|
2
|
+
|
|
3
|
+
The SOAJS Controller provides special built-in routes that are handled directly by the gateway rather than being proxied to backend services.
|
|
4
|
+
|
|
5
|
+
## Route Overview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
9
|
+
│ BUILT-IN GATEWAY ROUTES │
|
|
10
|
+
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
11
|
+
|
|
12
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ │
|
|
14
|
+
│ /soajs/acl │
|
|
15
|
+
│ ├── Method: GET │
|
|
16
|
+
│ ├── Purpose: Retrieve ACL/permissions for authenticated user │
|
|
17
|
+
│ ├── Requires: External key (header), OAuth token (query) │
|
|
18
|
+
│ └── Returns: ACL, packages, user info, tenant info │
|
|
19
|
+
│ │
|
|
20
|
+
│ /soajs/proxy │
|
|
21
|
+
│ ├── Method: Any │
|
|
22
|
+
│ ├── Purpose: Proxy requests to external URLs or cross-environment │
|
|
23
|
+
│ ├── Requires: proxyRoute query parameter │
|
|
24
|
+
│ └── Optional: __env, tCode, extKey parameters │
|
|
25
|
+
│ │
|
|
26
|
+
│ /proxy/redirect (DEPRECATED → use /soajs/proxy) │
|
|
27
|
+
│ │
|
|
28
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 1. ACL Route (`/soajs/acl`)
|
|
34
|
+
|
|
35
|
+
**Endpoint:** `GET /soajs/acl`
|
|
36
|
+
|
|
37
|
+
**Purpose:** Returns the Access Control List (ACL) and permissions for the currently authenticated user. This route is useful for frontend applications to determine what services and APIs the user has access to.
|
|
38
|
+
|
|
39
|
+
### Required Headers
|
|
40
|
+
|
|
41
|
+
| Header | Description |
|
|
42
|
+
|--------|-------------|
|
|
43
|
+
| `key` | External tenant key (required) |
|
|
44
|
+
|
|
45
|
+
### Query Parameters
|
|
46
|
+
|
|
47
|
+
| Parameter | Description |
|
|
48
|
+
|-----------|-------------|
|
|
49
|
+
| `access_token` | OAuth2 access token for user-specific ACL |
|
|
50
|
+
|
|
51
|
+
### Response Structure
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
{
|
|
55
|
+
"acl": { // Raw ACL from tenant application or package
|
|
56
|
+
"serviceName": {
|
|
57
|
+
"version": {
|
|
58
|
+
"access": true,
|
|
59
|
+
"apisPermission": "restricted",
|
|
60
|
+
"get": { "apis": { "/api/path": {} } }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"finalACL": { // Computed ACL with latest versions
|
|
65
|
+
"serviceName": {
|
|
66
|
+
"version": "1",
|
|
67
|
+
"get": ["/api/path"] // Allowed APIs per method (if restricted)
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"packages": ["PACKAGE_CODE"], // Allowed product packages
|
|
71
|
+
"urac": { // User info (if authenticated)
|
|
72
|
+
"_id": "user_id"
|
|
73
|
+
},
|
|
74
|
+
"tenant": { // Tenant info
|
|
75
|
+
"id": "tenant_id",
|
|
76
|
+
"name": "Tenant Name",
|
|
77
|
+
"code": "TCODE",
|
|
78
|
+
"type": "product"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Example
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Get ACL for authenticated user
|
|
87
|
+
curl -X GET "http://api.example.com/soajs/acl?access_token=YOUR_TOKEN" \
|
|
88
|
+
-H "key: YOUR_EXTERNAL_KEY"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Error Codes
|
|
92
|
+
|
|
93
|
+
| Code | Description |
|
|
94
|
+
|------|-------------|
|
|
95
|
+
| 132 | Missing or invalid external key |
|
|
96
|
+
| 400 | OAuth token required but not provided |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 2. Proxy Route (`/soajs/proxy`)
|
|
101
|
+
|
|
102
|
+
**Endpoint:** `ANY /soajs/proxy`
|
|
103
|
+
|
|
104
|
+
**Purpose:** Proxies requests to external URLs or to services in other SOAJS environments. Supports cross-environment communication with automatic key resolution.
|
|
105
|
+
|
|
106
|
+
### Required Headers
|
|
107
|
+
|
|
108
|
+
| Header | Description |
|
|
109
|
+
|--------|-------------|
|
|
110
|
+
| `key` | External tenant key |
|
|
111
|
+
|
|
112
|
+
### Query Parameters
|
|
113
|
+
|
|
114
|
+
| Parameter | Required | Description |
|
|
115
|
+
|-----------|----------|-------------|
|
|
116
|
+
| `proxyRoute` | Yes | URL-encoded target route (full URL or service path) |
|
|
117
|
+
| `__env` | No | Target environment code (e.g., "STG", "PROD") for cross-environment |
|
|
118
|
+
| `tCode` | No | Tenant code for automatic key lookup in target environment |
|
|
119
|
+
| `extKey` | No | Explicit external key to use for target environment |
|
|
120
|
+
| `access_token` | No | OAuth token to forward |
|
|
121
|
+
|
|
122
|
+
### Usage Modes
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
126
|
+
│ PROXY REQUEST MODES │
|
|
127
|
+
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
128
|
+
|
|
129
|
+
Mode 1: Direct URL Proxy
|
|
130
|
+
─────────────────────────
|
|
131
|
+
proxyRoute=http://service:port/path
|
|
132
|
+
|
|
133
|
+
Request flows directly to the specified URL.
|
|
134
|
+
No environment lookup required.
|
|
135
|
+
|
|
136
|
+
Mode 2: Cross-Environment Proxy
|
|
137
|
+
────────────────────────────────
|
|
138
|
+
proxyRoute=/service/api&__env=PROD&tCode=TENANT
|
|
139
|
+
|
|
140
|
+
1. Loads target environment registry
|
|
141
|
+
2. Looks up tenant's external key for that environment
|
|
142
|
+
3. Constructs URL from registry (protocol://domain:port)
|
|
143
|
+
4. Forwards request with remote ext key
|
|
144
|
+
|
|
145
|
+
Mode 3: Cross-Environment with Explicit Key
|
|
146
|
+
───────────────────────────────────────────
|
|
147
|
+
proxyRoute=/service/api&__env=PROD&extKey=xxx
|
|
148
|
+
|
|
149
|
+
Uses the provided extKey instead of looking up tenant key.
|
|
150
|
+
|
|
151
|
+
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Examples
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Direct URL proxy
|
|
158
|
+
curl -X GET "http://api.example.com/soajs/proxy?proxyRoute=http%3A%2F%2F127.0.0.1%3A4002%2FCheckPhoneNumber&access_token=TOKEN" \
|
|
159
|
+
-H "key: YOUR_EXTERNAL_KEY"
|
|
160
|
+
|
|
161
|
+
# Cross-environment proxy with automatic key resolution
|
|
162
|
+
curl -X GET "http://api.example.com/soajs/proxy?proxyRoute=%2Furac%2FgetUser&__env=STG&access_token=TOKEN" \
|
|
163
|
+
-H "key: YOUR_EXTERNAL_KEY"
|
|
164
|
+
|
|
165
|
+
# Cross-environment proxy with explicit key
|
|
166
|
+
curl -X POST "http://api.example.com/soajs/proxy?proxyRoute=%2Fservice%2Fapi&__env=PROD&extKey=REMOTE_KEY" \
|
|
167
|
+
-H "key: YOUR_EXTERNAL_KEY" \
|
|
168
|
+
-H "Content-Type: application/json" \
|
|
169
|
+
-d '{"data": "value"}'
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Error Codes
|
|
173
|
+
|
|
174
|
+
| Code | Description |
|
|
175
|
+
|------|-------------|
|
|
176
|
+
| 135 | Invalid proxy URL or connection failed |
|
|
177
|
+
| 137 | No external key found for tenant in target environment |
|
|
178
|
+
| 139 | Missing proxyRoute parameter |
|
|
179
|
+
| 207 | Failed to load target environment registry |
|
|
180
|
+
| 208 | Target environment registry missing protocol/domain/port |
|
|
181
|
+
|
|
182
|
+
### Request Flow
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
┌──────────────────────────────────────────────────────────────────────────────────┐
|
|
186
|
+
│ PROXY REQUEST FLOW │
|
|
187
|
+
└──────────────────────────────────────────────────────────────────────────────────┘
|
|
188
|
+
|
|
189
|
+
Client Request
|
|
190
|
+
│
|
|
191
|
+
▼
|
|
192
|
+
┌─────────────────┐
|
|
193
|
+
│ Parse Query │
|
|
194
|
+
│ Parameters │
|
|
195
|
+
└────────┬────────┘
|
|
196
|
+
│
|
|
197
|
+
├─── proxyRoute (required)
|
|
198
|
+
├─── __env (optional)
|
|
199
|
+
├─── tCode (optional)
|
|
200
|
+
└─── extKey (optional)
|
|
201
|
+
│
|
|
202
|
+
▼
|
|
203
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
204
|
+
│ __env │ NO │ Direct Proxy │
|
|
205
|
+
│ provided? │───▶│ to proxyRoute │
|
|
206
|
+
└────────┬────────┘ └─────────────────┘
|
|
207
|
+
│ YES
|
|
208
|
+
▼
|
|
209
|
+
┌─────────────────┐
|
|
210
|
+
│ Load Remote │
|
|
211
|
+
│ Environment │
|
|
212
|
+
│ Registry │
|
|
213
|
+
└────────┬────────┘
|
|
214
|
+
│
|
|
215
|
+
▼
|
|
216
|
+
┌─────────────────┐ ┌─────────────────┐
|
|
217
|
+
│ extKey │YES │ Use Provided │
|
|
218
|
+
│ provided? │───▶│ extKey │
|
|
219
|
+
└────────┬────────┘ └────────┬────────┘
|
|
220
|
+
│ NO │
|
|
221
|
+
▼ │
|
|
222
|
+
┌─────────────────┐ │
|
|
223
|
+
│ Lookup Tenant │ │
|
|
224
|
+
│ Key for Env │ │
|
|
225
|
+
└────────┬────────┘ │
|
|
226
|
+
│ │
|
|
227
|
+
└──────────┬───────────┘
|
|
228
|
+
│
|
|
229
|
+
▼
|
|
230
|
+
┌─────────────────────────────────────────┐
|
|
231
|
+
│ Construct Full URL │
|
|
232
|
+
│ protocol://domain:port/proxyRoute │
|
|
233
|
+
└────────────────────┬────────────────────┘
|
|
234
|
+
│
|
|
235
|
+
▼
|
|
236
|
+
┌─────────────────────────────────────────┐
|
|
237
|
+
│ Forward Request with Headers │
|
|
238
|
+
│ • soajs_roaming: source environment │
|
|
239
|
+
│ • key: remote ext key (if applicable) │
|
|
240
|
+
│ • Original headers (except host) │
|
|
241
|
+
└────────────────────┬────────────────────┘
|
|
242
|
+
│
|
|
243
|
+
▼
|
|
244
|
+
Target Service
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 3. Deprecated: `/proxy/redirect`
|
|
250
|
+
|
|
251
|
+
**Status:** DEPRECATED
|
|
252
|
+
|
|
253
|
+
**Replacement:** Use `/soajs/proxy` instead
|
|
254
|
+
|
|
255
|
+
This route has identical functionality to `/soajs/proxy` but is deprecated. The gateway will log a warning when this route is used:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
Route: [/proxy/redirect] is deprecated. You should use [/soajs/proxy].
|
|
259
|
+
```
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# Maintenance Routes
|
|
2
|
+
|
|
3
|
+
The SOAJS Controller provides maintenance endpoints on a separate port (default: 5000) for health checks, configuration management, and system administration.
|
|
4
|
+
|
|
5
|
+
## Server Overview
|
|
6
|
+
|
|
7
|
+
**File:** `server/maintenance.js`
|
|
8
|
+
|
|
9
|
+
**Default Port:** 5000
|
|
10
|
+
|
|
11
|
+
The maintenance server runs on a separate port from the main gateway to allow internal access for health checks and administration without exposing these endpoints publicly.
|
|
12
|
+
|
|
13
|
+
## Available Endpoints
|
|
14
|
+
|
|
15
|
+
| Endpoint | Method | Purpose |
|
|
16
|
+
|----------|--------|---------|
|
|
17
|
+
| `/heartbeat` | GET | Basic health check |
|
|
18
|
+
| `/loadProvision` | GET | Reload provision/tenant data |
|
|
19
|
+
| `/reloadRegistry` | GET | Reload environment registry |
|
|
20
|
+
| `/awarenessStat` | GET | Get service awareness statistics |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 1. Heartbeat (`/heartbeat`)
|
|
25
|
+
|
|
26
|
+
**Endpoint:** `GET /heartbeat`
|
|
27
|
+
|
|
28
|
+
**Purpose:** Basic health check to verify the gateway is running.
|
|
29
|
+
|
|
30
|
+
### Response
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
{
|
|
34
|
+
"result": true,
|
|
35
|
+
"ts": 1699999999999, // Timestamp
|
|
36
|
+
"service": {
|
|
37
|
+
"service": "controller",
|
|
38
|
+
"type": "rest",
|
|
39
|
+
"route": "/heartbeat"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Usage
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
curl http://localhost:5000/heartbeat
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Kubernetes/Docker Health Probes
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
# Kubernetes
|
|
54
|
+
livenessProbe:
|
|
55
|
+
httpGet:
|
|
56
|
+
path: /heartbeat
|
|
57
|
+
port: 5000
|
|
58
|
+
initialDelaySeconds: 30
|
|
59
|
+
periodSeconds: 10
|
|
60
|
+
|
|
61
|
+
readinessProbe:
|
|
62
|
+
httpGet:
|
|
63
|
+
path: /heartbeat
|
|
64
|
+
port: 5000
|
|
65
|
+
initialDelaySeconds: 5
|
|
66
|
+
periodSeconds: 5
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 2. Load Provision (`/loadProvision`)
|
|
72
|
+
|
|
73
|
+
**Endpoint:** `GET /loadProvision`
|
|
74
|
+
|
|
75
|
+
**Purpose:** Reloads tenant, key, and package data from the Core DB.
|
|
76
|
+
|
|
77
|
+
### Response
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
{
|
|
81
|
+
"result": true,
|
|
82
|
+
"ts": 1699999999999,
|
|
83
|
+
"service": {
|
|
84
|
+
"service": "controller",
|
|
85
|
+
"type": "rest",
|
|
86
|
+
"route": "/loadProvision"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Usage
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
curl http://localhost:5000/loadProvision
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### When to Use
|
|
98
|
+
|
|
99
|
+
- After updating tenant configurations
|
|
100
|
+
- After modifying application keys
|
|
101
|
+
- After changing package ACLs
|
|
102
|
+
- To force refresh of cached provision data
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 3. Reload Registry (`/reloadRegistry`)
|
|
107
|
+
|
|
108
|
+
**Endpoint:** `GET /reloadRegistry`
|
|
109
|
+
|
|
110
|
+
**Purpose:** Reloads the environment registry from the Core DB.
|
|
111
|
+
|
|
112
|
+
### Response
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
{
|
|
116
|
+
"result": true,
|
|
117
|
+
"ts": 1699999999999,
|
|
118
|
+
"service": {
|
|
119
|
+
"service": "controller",
|
|
120
|
+
"type": "rest",
|
|
121
|
+
"route": "/reloadRegistry"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Usage
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
curl http://localhost:5000/reloadRegistry
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### What Gets Reloaded
|
|
133
|
+
|
|
134
|
+
- Service definitions and hosts
|
|
135
|
+
- Database configurations
|
|
136
|
+
- Service config (throttling, CORS, OAuth)
|
|
137
|
+
- Custom gateway settings
|
|
138
|
+
- All environment-specific settings
|
|
139
|
+
|
|
140
|
+
### When to Use
|
|
141
|
+
|
|
142
|
+
- After modifying environment configuration
|
|
143
|
+
- After adding new services
|
|
144
|
+
- After changing service hosts
|
|
145
|
+
- After modifying custom registry settings
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 4. Awareness Statistics (`/awarenessStat`)
|
|
150
|
+
|
|
151
|
+
**Endpoint:** `GET /awarenessStat`
|
|
152
|
+
|
|
153
|
+
**Purpose:** Returns the current state of service awareness/discovery.
|
|
154
|
+
|
|
155
|
+
### Response (Custom Mode)
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
{
|
|
159
|
+
"result": true,
|
|
160
|
+
"ts": 1699999999999,
|
|
161
|
+
"service": {
|
|
162
|
+
"service": "controller",
|
|
163
|
+
"type": "rest",
|
|
164
|
+
"route": "/awarenessStat"
|
|
165
|
+
},
|
|
166
|
+
"data": {
|
|
167
|
+
"services": {
|
|
168
|
+
"oauth": {
|
|
169
|
+
"1": {
|
|
170
|
+
"hosts": ["host1.local:4002", "host2.local:4002"],
|
|
171
|
+
"healthy": 2
|
|
172
|
+
},
|
|
173
|
+
"2": {
|
|
174
|
+
"hosts": ["host3.local:4002"],
|
|
175
|
+
"healthy": 1
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"urac": {
|
|
179
|
+
"3": {
|
|
180
|
+
"hosts": ["host1.local:4001"],
|
|
181
|
+
"healthy": 1
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Response (HA Mode)
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
{
|
|
193
|
+
"result": true,
|
|
194
|
+
"ts": 1699999999999,
|
|
195
|
+
"service": {
|
|
196
|
+
"service": "controller",
|
|
197
|
+
"type": "rest",
|
|
198
|
+
"route": "/awarenessStat"
|
|
199
|
+
},
|
|
200
|
+
"data": {
|
|
201
|
+
"mode": "kubernetes",
|
|
202
|
+
"services": {
|
|
203
|
+
"oauth": {
|
|
204
|
+
"1": {
|
|
205
|
+
"pods": ["oauth-v1-abc123", "oauth-v1-def456"],
|
|
206
|
+
"healthy": 2
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Usage
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
curl http://localhost:5000/awarenessStat
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### When to Use
|
|
221
|
+
|
|
222
|
+
- To verify service discovery is working
|
|
223
|
+
- To check service health status
|
|
224
|
+
- To debug routing issues
|
|
225
|
+
- To monitor cluster state
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Security Considerations
|
|
230
|
+
|
|
231
|
+
### Network Access
|
|
232
|
+
|
|
233
|
+
The maintenance port should only be accessible from:
|
|
234
|
+
- Internal networks
|
|
235
|
+
- Kubernetes cluster (for probes)
|
|
236
|
+
- Monitoring systems
|
|
237
|
+
|
|
238
|
+
### Firewall Rules
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
# Example: Only allow internal access to maintenance port
|
|
242
|
+
iptables -A INPUT -p tcp --dport 5000 -s 10.0.0.0/8 -j ACCEPT
|
|
243
|
+
iptables -A INPUT -p tcp --dport 5000 -j DROP
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Kubernetes NetworkPolicy
|
|
247
|
+
|
|
248
|
+
```yaml
|
|
249
|
+
apiVersion: networking.k8s.io/v1
|
|
250
|
+
kind: NetworkPolicy
|
|
251
|
+
metadata:
|
|
252
|
+
name: controller-maintenance
|
|
253
|
+
spec:
|
|
254
|
+
podSelector:
|
|
255
|
+
matchLabels:
|
|
256
|
+
soajs.service.name: controller
|
|
257
|
+
ingress:
|
|
258
|
+
- from:
|
|
259
|
+
- namespaceSelector:
|
|
260
|
+
matchLabels:
|
|
261
|
+
name: monitoring
|
|
262
|
+
ports:
|
|
263
|
+
- port: 5000
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Integration with Monitoring
|
|
269
|
+
|
|
270
|
+
### Prometheus Metrics
|
|
271
|
+
|
|
272
|
+
The heartbeat endpoint can be used with Prometheus blackbox exporter:
|
|
273
|
+
|
|
274
|
+
```yaml
|
|
275
|
+
# prometheus.yml
|
|
276
|
+
scrape_configs:
|
|
277
|
+
- job_name: 'soajs-controller'
|
|
278
|
+
metrics_path: /probe
|
|
279
|
+
params:
|
|
280
|
+
module: [http_2xx]
|
|
281
|
+
static_configs:
|
|
282
|
+
- targets:
|
|
283
|
+
- http://controller:5000/heartbeat
|
|
284
|
+
relabel_configs:
|
|
285
|
+
- source_labels: [__address__]
|
|
286
|
+
target_label: __param_target
|
|
287
|
+
- source_labels: [__param_target]
|
|
288
|
+
target_label: instance
|
|
289
|
+
- target_label: __address__
|
|
290
|
+
replacement: blackbox-exporter:9115
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Health Check Scripts
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
#!/bin/bash
|
|
297
|
+
# health-check.sh
|
|
298
|
+
|
|
299
|
+
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/heartbeat)
|
|
300
|
+
|
|
301
|
+
if [ "$RESPONSE" == "200" ]; then
|
|
302
|
+
echo "Gateway is healthy"
|
|
303
|
+
exit 0
|
|
304
|
+
else
|
|
305
|
+
echo "Gateway health check failed: HTTP $RESPONSE"
|
|
306
|
+
exit 1
|
|
307
|
+
fi
|
|
308
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Awareness Middleware
|
|
2
|
+
|
|
3
|
+
**File:** `mw/awareness/index.js`
|
|
4
|
+
|
|
5
|
+
**Order:** 9
|
|
6
|
+
|
|
7
|
+
The Awareness middleware provides service discovery functions for resolving service hosts.
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
- Attaches service discovery functions to `req.soajs.awareness`
|
|
12
|
+
- Supports both Custom mode (static registry) and HA mode (Kubernetes/Swarm)
|
|
13
|
+
- Provides host resolution and version lookup
|
|
14
|
+
|
|
15
|
+
## Flow
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Incoming Request
|
|
19
|
+
│
|
|
20
|
+
▼
|
|
21
|
+
┌─────────────────────┐
|
|
22
|
+
│ Determine Mode │ process.env.SOAJS_DEPLOY_HA?
|
|
23
|
+
│ Custom or HA │
|
|
24
|
+
└────────┬────────────┘
|
|
25
|
+
│
|
|
26
|
+
├─── No HA ──▶ Use custom.js driver
|
|
27
|
+
│
|
|
28
|
+
├─── HA ──▶ Use ha.js driver
|
|
29
|
+
│
|
|
30
|
+
▼
|
|
31
|
+
┌─────────────────────┐
|
|
32
|
+
│ Attach Awareness │ req.soajs.awareness = { ... }
|
|
33
|
+
│ Functions │
|
|
34
|
+
└────────┬────────────┘
|
|
35
|
+
│
|
|
36
|
+
▼
|
|
37
|
+
next()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Drivers
|
|
41
|
+
|
|
42
|
+
### Custom Mode (Non-HA)
|
|
43
|
+
|
|
44
|
+
**File:** `mw/awareness/custom.js`
|
|
45
|
+
|
|
46
|
+
- Uses registry's static host lists
|
|
47
|
+
- In-memory health tracking
|
|
48
|
+
- Round-robin load balancing
|
|
49
|
+
|
|
50
|
+
### HA Mode (Kubernetes/Swarm)
|
|
51
|
+
|
|
52
|
+
**File:** `mw/awareness/ha.js`
|
|
53
|
+
|
|
54
|
+
- Uses infrastructure module for discovery
|
|
55
|
+
- Dynamic service resolution via cluster API
|
|
56
|
+
- Automatic health monitoring
|
|
57
|
+
|
|
58
|
+
## Methods Added
|
|
59
|
+
|
|
60
|
+
### `req.soajs.awareness.getHost(serviceName, [version], callback)`
|
|
61
|
+
|
|
62
|
+
Resolves a host for the given service.
|
|
63
|
+
|
|
64
|
+
**Parameters:**
|
|
65
|
+
- `serviceName` - Name of the service
|
|
66
|
+
- `version` - Service version (optional)
|
|
67
|
+
- `callback` - Function receiving `(host)` where host is `"hostname:port"` or `null`
|
|
68
|
+
|
|
69
|
+
**Example:**
|
|
70
|
+
```javascript
|
|
71
|
+
req.soajs.awareness.getHost("oauth", "1", (host) => {
|
|
72
|
+
if (host) {
|
|
73
|
+
// host = "oauth-service:4002"
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### `req.soajs.awareness.getLatestVersion(serviceName, callback)`
|
|
79
|
+
|
|
80
|
+
Gets the latest available version of a service.
|
|
81
|
+
|
|
82
|
+
**Parameters:**
|
|
83
|
+
- `serviceName` - Name of the service
|
|
84
|
+
- `callback` - Function receiving `(version)` as string or `null`
|
|
85
|
+
|
|
86
|
+
**Example:**
|
|
87
|
+
```javascript
|
|
88
|
+
req.soajs.awareness.getLatestVersion("oauth", (version) => {
|
|
89
|
+
// version = "2"
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### `req.soajs.awareness.getLatestVersionFromCluster(serviceName, callback)`
|
|
94
|
+
|
|
95
|
+
(HA mode only) Gets the latest version directly from the cluster.
|
|
96
|
+
|
|
97
|
+
**Example:**
|
|
98
|
+
```javascript
|
|
99
|
+
if (process.env.SOAJS_DEPLOY_HA) {
|
|
100
|
+
req.soajs.awareness.getLatestVersionFromCluster("oauth", (version) => {
|
|
101
|
+
// Fresh lookup from K8s/Swarm API
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Configuration
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
{
|
|
110
|
+
"awareness": true, // Enable awareness
|
|
111
|
+
"doNotRebuildCache": false // Skip initial cache build (HA mode)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Usage Notes
|
|
116
|
+
|
|
117
|
+
- Custom mode caches hosts in memory, updated via heartbeat
|
|
118
|
+
- HA mode queries cluster API for each lookup (with caching)
|
|
119
|
+
- Version can be omitted to get any available host
|
|
120
|
+
- Returns `null` if service/version not found
|