@furystack/rest-service 10.0.28 → 10.1.1
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/README.md +249 -12
- package/esm/api-manager.d.ts +1 -3
- package/esm/api-manager.d.ts.map +1 -1
- package/esm/api-manager.js +4 -6
- package/esm/api-manager.js.map +1 -1
- package/esm/header-processor.d.ts +39 -0
- package/esm/header-processor.d.ts.map +1 -0
- package/esm/header-processor.js +113 -0
- package/esm/header-processor.js.map +1 -0
- package/esm/header-processor.spec.d.ts +2 -0
- package/esm/header-processor.spec.d.ts.map +1 -0
- package/esm/header-processor.spec.js +420 -0
- package/esm/header-processor.spec.js.map +1 -0
- package/esm/helpers.d.ts +69 -1
- package/esm/helpers.d.ts.map +1 -1
- package/esm/helpers.js +70 -1
- package/esm/helpers.js.map +1 -1
- package/esm/helpers.spec.js +21 -5
- package/esm/helpers.spec.js.map +1 -1
- package/esm/http-proxy-handler.d.ts +53 -0
- package/esm/http-proxy-handler.d.ts.map +1 -0
- package/esm/http-proxy-handler.js +179 -0
- package/esm/http-proxy-handler.js.map +1 -0
- package/esm/http-user-context.d.ts +4 -4
- package/esm/http-user-context.d.ts.map +1 -1
- package/esm/http-user-context.js +4 -4
- package/esm/http-user-context.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/path-processor.d.ts +33 -0
- package/esm/path-processor.d.ts.map +1 -0
- package/esm/path-processor.js +58 -0
- package/esm/path-processor.js.map +1 -0
- package/esm/path-processor.spec.d.ts +2 -0
- package/esm/path-processor.spec.d.ts.map +1 -0
- package/esm/path-processor.spec.js +256 -0
- package/esm/path-processor.spec.js.map +1 -0
- package/esm/proxy-manager.d.ts +52 -0
- package/esm/proxy-manager.d.ts.map +1 -0
- package/esm/proxy-manager.js +84 -0
- package/esm/proxy-manager.js.map +1 -0
- package/esm/proxy-manager.spec.d.ts +2 -0
- package/esm/proxy-manager.spec.d.ts.map +1 -0
- package/esm/proxy-manager.spec.js +1781 -0
- package/esm/proxy-manager.spec.js.map +1 -0
- package/esm/server-manager.d.ts +7 -0
- package/esm/server-manager.d.ts.map +1 -1
- package/esm/server-manager.js +12 -0
- package/esm/server-manager.js.map +1 -1
- package/esm/static-server-manager.d.ts.map +1 -1
- package/esm/static-server-manager.js +5 -7
- package/esm/static-server-manager.js.map +1 -1
- package/esm/websocket-proxy-handler.d.ts +44 -0
- package/esm/websocket-proxy-handler.d.ts.map +1 -0
- package/esm/websocket-proxy-handler.js +157 -0
- package/esm/websocket-proxy-handler.js.map +1 -0
- package/package.json +12 -10
- package/src/api-manager.ts +5 -15
- package/src/header-processor.spec.ts +514 -0
- package/src/header-processor.ts +140 -0
- package/src/helpers.spec.ts +23 -5
- package/src/helpers.ts +72 -1
- package/src/http-proxy-handler.ts +215 -0
- package/src/http-user-context.ts +6 -6
- package/src/index.ts +1 -0
- package/src/path-processor.spec.ts +318 -0
- package/src/path-processor.ts +69 -0
- package/src/proxy-manager.spec.ts +2094 -0
- package/src/proxy-manager.ts +101 -0
- package/src/server-manager.ts +19 -0
- package/src/static-server-manager.ts +5 -7
- package/src/websocket-proxy-handler.ts +204 -0
package/README.md
CHANGED
|
@@ -12,14 +12,20 @@ Usage example – authenticated GET, GET collection, and POST APIs for a custom
|
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
14
|
import { MyApi, MyEntity } from 'my-common-package'
|
|
15
|
+
import { Injector } from '@furystack/inject'
|
|
15
16
|
import {
|
|
16
17
|
createGetCollectionEndpoint,
|
|
17
18
|
createGetEntityEndpoint,
|
|
18
19
|
Authenticate,
|
|
19
20
|
createPostEndpoint,
|
|
21
|
+
useHttpAuthentication,
|
|
22
|
+
useRestService,
|
|
20
23
|
} from '@furystack/rest-service'
|
|
21
24
|
|
|
22
|
-
myInjector
|
|
25
|
+
const myInjector = new Injector()
|
|
26
|
+
useHttpAuthentication(myInjector)
|
|
27
|
+
await useRestService<MyApi>({
|
|
28
|
+
injector: myInjector,
|
|
23
29
|
port: 8080, // The port to listen on
|
|
24
30
|
root: '/api', // Routes will be joined on this root path
|
|
25
31
|
cors: {
|
|
@@ -95,11 +101,12 @@ export interface MyApiWithCustomEndpoint extends RestApi {
|
|
|
95
101
|
|
|
96
102
|
/** In the Backend code */
|
|
97
103
|
|
|
98
|
-
import { JsonResult } from '@furystack/rest-service'
|
|
104
|
+
import { JsonResult, useRestService } from '@furystack/rest-service'
|
|
99
105
|
|
|
100
106
|
const i = new Injector()
|
|
101
107
|
|
|
102
|
-
|
|
108
|
+
await useRestService<MyApiWithCustomEndpoint>({
|
|
109
|
+
injector: i,
|
|
103
110
|
port: 8080,
|
|
104
111
|
root: '/mockApi',
|
|
105
112
|
api: {
|
|
@@ -190,17 +197,247 @@ In that way, you will get full validation for _all_ defined endpoint data (heade
|
|
|
190
197
|
|
|
191
198
|
### Authentication and HttpUserContext
|
|
192
199
|
|
|
193
|
-
You can use the built-in authentication that comes with this package. It contains a session (~cookie) based authentication and Basic Auth. You can use it with the
|
|
200
|
+
You can use the built-in authentication that comes with this package. It contains a session (~cookie) based authentication and Basic Auth. You can use it with the `useHttpAuthentication()` helper:
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
import { useHttpAuthentication, useRestService } from '@furystack/rest-service'
|
|
204
|
+
import { Injector } from '@furystack/inject'
|
|
205
|
+
|
|
206
|
+
const myInjector = new Injector()
|
|
207
|
+
useHttpAuthentication(myInjector, {
|
|
208
|
+
cookieName: 'sessionId', // The session ID will be stored in this cookie
|
|
209
|
+
enableBasicAuth: true, // Enables / disables standard Basic Authentication
|
|
210
|
+
model: ApplicationUserModel, // The custom User model. Should implement `User`
|
|
211
|
+
getUserStore: (storeManager) => storeManager.getStoreFor(ApplicationUserModel, 'username'), // Callback to retrieve the User Store
|
|
212
|
+
getSessionStore: (storeManager) => storeManager.getStoreFor(MySessionModel, 'sessionId'), // Callback to retrieve the Session Store
|
|
213
|
+
})
|
|
214
|
+
await useRestService<MyApi>({ injector: myInjector, ...apiOptions })
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Static File Serving
|
|
218
|
+
|
|
219
|
+
You can serve static files using the `useStaticFiles` helper:
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
import { useStaticFiles } from '@furystack/rest-service'
|
|
223
|
+
|
|
224
|
+
await useStaticFiles({
|
|
225
|
+
injector,
|
|
226
|
+
baseUrl: '/static',
|
|
227
|
+
path: './public',
|
|
228
|
+
port: 3000,
|
|
229
|
+
fallback: 'index.html', // Optional fallback file
|
|
230
|
+
headers: {
|
|
231
|
+
'Cache-Control': 'public, max-age=3600',
|
|
232
|
+
},
|
|
233
|
+
})
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### HTTP Proxying
|
|
237
|
+
|
|
238
|
+
You can set up HTTP proxying with header and cookie transformation using the `useProxy` helper. The proxy functionality forwards requests to target servers and returns their responses:
|
|
194
239
|
|
|
195
240
|
```ts
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
241
|
+
import { useProxy } from '@furystack/rest-service'
|
|
242
|
+
|
|
243
|
+
// Basic proxy (forwards requests to target server)
|
|
244
|
+
await useProxy({
|
|
245
|
+
injector,
|
|
246
|
+
sourceBaseUrl: '/old',
|
|
247
|
+
targetBaseUrl: 'https://example.com',
|
|
248
|
+
pathRewrite: (path) => path.replace('/path', '/new'),
|
|
249
|
+
sourcePort: 3000,
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
// Proxy with header transformation
|
|
253
|
+
await useProxy({
|
|
254
|
+
injector,
|
|
255
|
+
sourceBaseUrl: '/api/v1',
|
|
256
|
+
targetBaseUrl: 'https://api.example.com',
|
|
257
|
+
pathRewrite: (path) => path.replace('/legacy', '/v2'),
|
|
258
|
+
sourcePort: 3000,
|
|
259
|
+
headers: (originalHeaders) => ({
|
|
260
|
+
'X-API-Version': 'v2',
|
|
261
|
+
Authorization: 'Bearer new-token',
|
|
262
|
+
'X-Forwarded-For': originalHeaders['x-forwarded-for'] || 'unknown',
|
|
263
|
+
}),
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// Proxy with request cookie transformation
|
|
267
|
+
await useProxy({
|
|
268
|
+
injector,
|
|
269
|
+
sourceBaseUrl: '/auth',
|
|
270
|
+
targetBaseUrl: 'https://auth.example.com',
|
|
271
|
+
pathRewrite: (path) => path.replace('/login', '/signin'),
|
|
272
|
+
sourcePort: 3000,
|
|
273
|
+
cookies: (originalCookies) => [
|
|
274
|
+
...originalCookies.filter((c) => !c.startsWith('old-session=')),
|
|
275
|
+
'new-session=updated-session-id',
|
|
276
|
+
'auth-provider=oauth2',
|
|
277
|
+
],
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
// Proxy with response cookie transformation
|
|
281
|
+
await useProxy({
|
|
282
|
+
injector,
|
|
283
|
+
sourceBaseUrl: '/api',
|
|
284
|
+
targetBaseUrl: 'https://api.example.com',
|
|
285
|
+
sourcePort: 3000,
|
|
286
|
+
responseCookies: (setCookies) => {
|
|
287
|
+
// Transform Set-Cookie headers from the target server
|
|
288
|
+
return setCookies.map((cookie) => {
|
|
289
|
+
// Change domain from target to your domain
|
|
290
|
+
return cookie.replace('domain=api.example.com', 'domain=myapp.com')
|
|
291
|
+
})
|
|
292
|
+
},
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
// Proxy with timeout configuration
|
|
296
|
+
await useProxy({
|
|
297
|
+
injector,
|
|
298
|
+
sourceBaseUrl: '/api',
|
|
299
|
+
targetBaseUrl: 'https://slow-api.example.com',
|
|
300
|
+
sourcePort: 3000,
|
|
301
|
+
timeout: 5000, // 5 second timeout (default is 30000ms)
|
|
302
|
+
})
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**How Proxying Works:**
|
|
306
|
+
|
|
307
|
+
1. **Client makes request** to source URL (e.g., `GET /old/path`)
|
|
308
|
+
2. **Proxy server forwards request** to target URL (e.g., `https://example.com/new/path`)
|
|
309
|
+
3. **Target server responds** with content
|
|
310
|
+
4. **Proxy server returns response** to client
|
|
311
|
+
|
|
312
|
+
The proxy server acts as an intermediary, forwarding requests and responses while allowing header and cookie transformation.
|
|
313
|
+
|
|
314
|
+
**Error Handling and Monitoring:**
|
|
315
|
+
|
|
316
|
+
The proxy emits events when requests fail, allowing you to monitor and log errors:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
import { ProxyManager } from '@furystack/rest-service'
|
|
320
|
+
|
|
321
|
+
// Set up error monitoring
|
|
322
|
+
const proxyManager = injector.getInstance(ProxyManager)
|
|
323
|
+
proxyManager.subscribe('onProxyFailed', ({ from, to, error }) => {
|
|
324
|
+
console.error(`Proxy failed: ${from} -> ${to}`, error)
|
|
325
|
+
// Send to your logging service
|
|
326
|
+
})
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
When the target server is unreachable or returns an error, the proxy returns `502 Bad Gateway` to the client. Errors are also emitted via the `onProxyFailed` event for monitoring.
|
|
330
|
+
|
|
331
|
+
**Configuration Options:**
|
|
332
|
+
|
|
333
|
+
- `timeout` (optional, default: 30000ms): Maximum time in milliseconds to wait for the target server to respond. If exceeded, the request is aborted and a 502 error is returned.
|
|
334
|
+
- `sourceBaseUrl`: The base URL path to match for proxying (e.g., `/api`, `/old`). Can be specified with or without a trailing slash.
|
|
335
|
+
- `targetBaseUrl`: The target server URL (must be a valid HTTP/HTTPS URL).
|
|
336
|
+
- `pathRewrite`: Optional function to transform the path before forwarding.
|
|
337
|
+
- `headers`: Optional function to transform request headers. **Note**: This receives headers _after_ filtering hop-by-hop headers (Connection, Keep-Alive, Transfer-Encoding, Upgrade, etc.) for security and protocol compliance.
|
|
338
|
+
- `cookies`: Optional function to transform request cookies.
|
|
339
|
+
- `responseCookies`: Optional function to transform response Set-Cookie headers.
|
|
340
|
+
|
|
341
|
+
**WebSocket Support:**
|
|
342
|
+
|
|
343
|
+
WebSocket proxying can be enabled by setting `enableWebsockets: true`:
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
await useProxy({
|
|
347
|
+
injector,
|
|
348
|
+
sourceBaseUrl: '/ws',
|
|
349
|
+
targetBaseUrl: 'https://ws.example.com',
|
|
350
|
+
sourcePort: 3000,
|
|
351
|
+
enableWebsockets: true,
|
|
352
|
+
})
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
When enabled, the proxy will forward WebSocket upgrade requests to the target server, enabling bidirectional real-time communication. WebSocket connections support:
|
|
356
|
+
|
|
357
|
+
- Bidirectional message streaming (both text and binary)
|
|
358
|
+
- Path rewriting (applied to WebSocket upgrade requests)
|
|
359
|
+
- Header transformations (applied to upgrade requests)
|
|
360
|
+
- Timeout configuration (applies to upgrade handshake)
|
|
361
|
+
- Error monitoring via `onWebSocketProxyFailed` events
|
|
362
|
+
|
|
363
|
+
Monitor WebSocket proxy errors:
|
|
364
|
+
|
|
365
|
+
```ts
|
|
366
|
+
const proxyManager = injector.getInstance(ProxyManager)
|
|
367
|
+
proxyManager.subscribe('onWebSocketProxyFailed', ({ from, to, error }) => {
|
|
368
|
+
console.error(`WebSocket proxy failed: ${from} -> ${to}`, error)
|
|
369
|
+
})
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Notes and Tips:**
|
|
373
|
+
|
|
374
|
+
- `pathRewrite` receives the substring of the original request URL after `sourceBaseUrl`, including the leading slash and any query string (e.g., for `GET /old/path?q=1` and `sourceBaseUrl='/old'` it gets `'/path?q=1'`). If you need to preserve or remove query strings, handle it inside your function.
|
|
375
|
+
- The proxy automatically adds `X-Forwarded-For`, `X-Forwarded-Host`, and `X-Forwarded-Proto`. You can override or extend these via the `headers(originalHeaders)` transformer if needed.
|
|
376
|
+
- WebSocket proxying is opt-in via `enableWebsockets: true`. When enabled, both HTTP and WebSocket requests can be proxied through the same endpoint.
|
|
377
|
+
- Multiple `Set-Cookie` headers from the target are preserved and can be transformed with `responseCookies`. Depending on your HTTP client, retrieving multiple `Set-Cookie` values may require client-specific APIs.
|
|
378
|
+
- You can bind the proxy to a specific host via `sourceHostName`:
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
await useProxy({
|
|
382
|
+
injector,
|
|
383
|
+
sourceHostName: '127.0.0.1',
|
|
384
|
+
sourceBaseUrl: '/internal',
|
|
385
|
+
targetBaseUrl: 'https://internal.example.com',
|
|
386
|
+
sourcePort: 3001,
|
|
387
|
+
})
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Path Rewriting Examples:**
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
// Simple path replacement
|
|
394
|
+
pathRewrite: (path) => path.replace('/old-path', '/new-path')
|
|
395
|
+
|
|
396
|
+
// Complex path transformation
|
|
397
|
+
pathRewrite: (path) => {
|
|
398
|
+
// Remove version prefix and add new one
|
|
399
|
+
if (path.startsWith('/v1/')) {
|
|
400
|
+
return path.replace('/v1/', '/v2/')
|
|
401
|
+
}
|
|
402
|
+
// Add prefix to all other paths
|
|
403
|
+
return `/api${path}`
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Conditional rewriting based on path
|
|
407
|
+
pathRewrite: (path) => {
|
|
408
|
+
if (path.includes('/admin/')) {
|
|
409
|
+
return path.replace('/admin/', '/dashboard/')
|
|
410
|
+
}
|
|
411
|
+
return path
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Manipulating query strings
|
|
415
|
+
pathRewrite: (path) => {
|
|
416
|
+
const [pathname, query] = path.split('?')
|
|
417
|
+
const newPath = pathname.replace('/v1/', '/v2/')
|
|
418
|
+
// Preserve or modify query string
|
|
419
|
+
if (query) {
|
|
420
|
+
return `${newPath}?${query}&version=2`
|
|
421
|
+
}
|
|
422
|
+
return newPath
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Header Transformation Notes:**
|
|
427
|
+
|
|
428
|
+
The `headers` transformation function receives headers **after** filtering hop-by-hop headers. These headers are automatically excluded for security and protocol compliance:
|
|
429
|
+
|
|
430
|
+
```ts
|
|
431
|
+
headers: (filteredHeaders) => {
|
|
432
|
+
// filteredHeaders will NOT contain:
|
|
433
|
+
// - connection, keep-alive, transfer-encoding, upgrade, etc.
|
|
434
|
+
|
|
435
|
+
return {
|
|
436
|
+
...filteredHeaders,
|
|
437
|
+
'X-API-Key': 'your-api-key',
|
|
438
|
+
Authorization: 'Bearer token',
|
|
439
|
+
}
|
|
440
|
+
}
|
|
204
441
|
```
|
|
205
442
|
|
|
206
443
|
### Built-in Actions
|
package/esm/api-manager.d.ts
CHANGED
|
@@ -83,9 +83,7 @@ export type OnRequestOptions = OnRequest & {
|
|
|
83
83
|
supportedMethods: string[];
|
|
84
84
|
deserializeQueryParams?: (param: string) => Record<string, unknown>;
|
|
85
85
|
};
|
|
86
|
-
export declare class ApiManager
|
|
87
|
-
private readonly apis;
|
|
88
|
-
[Symbol.dispose](): void;
|
|
86
|
+
export declare class ApiManager {
|
|
89
87
|
private getSuportedMethods;
|
|
90
88
|
private compileApi;
|
|
91
89
|
addApi<T extends RestApi>({ api, hostName, port, root, cors, injector, deserializeQueryParams, enableGetSchema, name, description, version, }: ImplementApiOptions<T>): Promise<{
|
package/esm/api-manager.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-manager.d.ts","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAQnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAA;AACvE,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,qBAAqB,CAAA;AAE/D,OAAO,iCAAiC,CAAA;AAExC,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,OAAO,IAAI;KACpD,OAAO,IAAI,MAAM,CAAC,GAAG;SACnB,IAAI,IAAI,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,EAAE,OAAO,CAAA;SAAE,GAAG,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK;KACnH;CACF,CAAA;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,SAAS,OAAO;IACpD;;OAEG;IACH,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAA;IAC7B;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAA;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAA;IAC/C;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAA;IAClE,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;KAC1B,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,mBAAmB,EAAE;CACtC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG;IACzC,WAAW,EAAE,cAAc,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAA;IAClB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,sBAAsB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpE,CAAA;AAED,qBACa,
|
|
1
|
+
{"version":3,"file":"api-manager.d.ts","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":"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"}
|
package/esm/api-manager.js
CHANGED
|
@@ -22,10 +22,6 @@ import { readPostBody } from './read-post-body.js';
|
|
|
22
22
|
import { ServerManager } from './server-manager.js';
|
|
23
23
|
import './server-response-extensions.js';
|
|
24
24
|
let ApiManager = class ApiManager {
|
|
25
|
-
apis = new Map();
|
|
26
|
-
[Symbol.dispose]() {
|
|
27
|
-
this.apis.clear();
|
|
28
|
-
}
|
|
29
25
|
getSuportedMethods(api) {
|
|
30
26
|
return Object.keys(api);
|
|
31
27
|
}
|
|
@@ -85,7 +81,7 @@ let ApiManager = class ApiManager {
|
|
|
85
81
|
return options.method &&
|
|
86
82
|
options.url &&
|
|
87
83
|
(options.supportedMethods.includes(options.method) || options.method === 'OPTIONS') &&
|
|
88
|
-
PathHelper.
|
|
84
|
+
PathHelper.matchesBaseUrl(options.url, options.rootApiPath)
|
|
89
85
|
? true
|
|
90
86
|
: false;
|
|
91
87
|
}
|
|
@@ -138,7 +134,9 @@ let ApiManager = class ApiManager {
|
|
|
138
134
|
});
|
|
139
135
|
}
|
|
140
136
|
async onMessage(options) {
|
|
141
|
-
const
|
|
137
|
+
const protocol = 'http://';
|
|
138
|
+
const host = `${options.hostName || ServerManager.DEFAULT_HOST}:${options.port}`;
|
|
139
|
+
const fullUrl = new URL(PathHelper.joinUrl(`${protocol}${host}`, options.req.url));
|
|
142
140
|
if (options.cors) {
|
|
143
141
|
addCorsHeaders(options.cors, options.req, options.res);
|
|
144
142
|
}
|
package/esm/api-manager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-manager.js","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAExD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AACxD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAEzD,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mDAAmD,CAAA;AACzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,yDAAyD,CAAA;AACpG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,iCAAiC,CAAA;AAqFjC,IAAM,UAAU,GAAhB,MAAM,UAAU;
|
|
1
|
+
{"version":3,"file":"api-manager.js","sourceRoot":"","sources":["../src/api-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { IncomingMessage, OutgoingHttpHeaders } from 'http';
|
|
2
|
+
export interface HeaderProcessorOptions {
|
|
3
|
+
headers?: (originalHeaders: OutgoingHttpHeaders) => OutgoingHttpHeaders;
|
|
4
|
+
cookies?: (originalCookies: string[]) => string[];
|
|
5
|
+
}
|
|
6
|
+
export interface ProcessedHeaders {
|
|
7
|
+
proxyHeaders: Record<string, string>;
|
|
8
|
+
finalCookies: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Handles header filtering, transformation, and cookie processing for proxy requests
|
|
12
|
+
*/
|
|
13
|
+
export declare class HeaderProcessor {
|
|
14
|
+
/**
|
|
15
|
+
* Filters out hop-by-hop headers that should not be forwarded
|
|
16
|
+
*/
|
|
17
|
+
filterHeaders(headers: OutgoingHttpHeaders): OutgoingHttpHeaders;
|
|
18
|
+
/**
|
|
19
|
+
* Processes cookies from the request
|
|
20
|
+
*/
|
|
21
|
+
processCookies(req: IncomingMessage, cookieTransformer?: (cookies: string[]) => string[]): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Builds X-Forwarded-* headers
|
|
24
|
+
*/
|
|
25
|
+
buildForwardedHeaders(req: IncomingMessage, targetHost: string): Record<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* Converts OutgoingHttpHeaders to a plain string record, excluding cookies and hop-by-hop headers
|
|
28
|
+
*/
|
|
29
|
+
convertHeadersToRecord(headers: OutgoingHttpHeaders): Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Processes all request headers and returns proxy-ready headers
|
|
32
|
+
*/
|
|
33
|
+
processRequestHeaders(req: IncomingMessage, targetHost: string, options?: HeaderProcessorOptions): ProcessedHeaders;
|
|
34
|
+
/**
|
|
35
|
+
* Filters hop-by-hop headers from response headers
|
|
36
|
+
*/
|
|
37
|
+
isHopByHopHeader(headerName: string): boolean;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=header-processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-processor.d.ts","sourceRoot":"","sources":["../src/header-processor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAA;AAchE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,CAAC,eAAe,EAAE,mBAAmB,KAAK,mBAAmB,CAAA;IACvE,OAAO,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;CAClD;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,YAAY,EAAE,MAAM,EAAE,CAAA;CACvB;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACI,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB;IAUvE;;OAEG;IACI,cAAc,CAAC,GAAG,EAAE,eAAe,EAAE,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,GAAG,MAAM,EAAE;IAK1G;;OAEG;IACI,qBAAqB,CAAC,GAAG,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAuB9F;;OAEG;IACI,sBAAsB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkBnF;;OAEG;IACI,qBAAqB,CAC1B,GAAG,EAAE,eAAe,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,sBAA2B,GACnC,gBAAgB;IA8BnB;;OAEG;IACI,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;CAGrD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Headers that should not be forwarded to the target server
|
|
2
|
+
const HOP_BY_HOP_HEADERS = new Set([
|
|
3
|
+
'connection',
|
|
4
|
+
'keep-alive',
|
|
5
|
+
'proxy-authenticate',
|
|
6
|
+
'proxy-authorization',
|
|
7
|
+
'te',
|
|
8
|
+
'trailer',
|
|
9
|
+
'transfer-encoding',
|
|
10
|
+
'upgrade',
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* Handles header filtering, transformation, and cookie processing for proxy requests
|
|
14
|
+
*/
|
|
15
|
+
export class HeaderProcessor {
|
|
16
|
+
/**
|
|
17
|
+
* Filters out hop-by-hop headers that should not be forwarded
|
|
18
|
+
*/
|
|
19
|
+
filterHeaders(headers) {
|
|
20
|
+
const filtered = {};
|
|
21
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
22
|
+
if (!HOP_BY_HOP_HEADERS.has(key.toLowerCase())) {
|
|
23
|
+
filtered[key] = value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return filtered;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Processes cookies from the request
|
|
30
|
+
*/
|
|
31
|
+
processCookies(req, cookieTransformer) {
|
|
32
|
+
const originalCookies = req.headers.cookie?.split(';').map((c) => c.trim()) ?? [];
|
|
33
|
+
return cookieTransformer ? cookieTransformer(originalCookies) : originalCookies;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Builds X-Forwarded-* headers
|
|
37
|
+
*/
|
|
38
|
+
buildForwardedHeaders(req, targetHost) {
|
|
39
|
+
const forwardedFor = [
|
|
40
|
+
req.headers['x-forwarded-for']
|
|
41
|
+
?.split(',')
|
|
42
|
+
.map((s) => s.trim())
|
|
43
|
+
.filter(Boolean) ?? [],
|
|
44
|
+
[req.socket.remoteAddress ?? ''],
|
|
45
|
+
]
|
|
46
|
+
.flat()
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.join(', ');
|
|
49
|
+
return {
|
|
50
|
+
Host: targetHost,
|
|
51
|
+
'User-Agent': req.headers['user-agent'] || 'FuryStack-Proxy/1.0',
|
|
52
|
+
'X-Forwarded-For': forwardedFor,
|
|
53
|
+
'X-Forwarded-Host': req.headers.host || '',
|
|
54
|
+
'X-Forwarded-Proto': req.headers['x-forwarded-proto'] ||
|
|
55
|
+
(req.socket.encrypted ? 'https' : 'http'),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Converts OutgoingHttpHeaders to a plain string record, excluding cookies and hop-by-hop headers
|
|
60
|
+
*/
|
|
61
|
+
convertHeadersToRecord(headers) {
|
|
62
|
+
const result = {};
|
|
63
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
64
|
+
const lowerKey = key.toLowerCase();
|
|
65
|
+
if (lowerKey !== 'cookie' && !HOP_BY_HOP_HEADERS.has(lowerKey)) {
|
|
66
|
+
if (typeof value === 'string') {
|
|
67
|
+
result[key] = value;
|
|
68
|
+
}
|
|
69
|
+
else if (typeof value === 'number') {
|
|
70
|
+
result[key] = value.toString();
|
|
71
|
+
}
|
|
72
|
+
else if (Array.isArray(value)) {
|
|
73
|
+
result[key] = value.join(', ');
|
|
74
|
+
}
|
|
75
|
+
// undefined is intentionally skipped
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Processes all request headers and returns proxy-ready headers
|
|
82
|
+
*/
|
|
83
|
+
processRequestHeaders(req, targetHost, options = {}) {
|
|
84
|
+
// Extract and normalize original headers
|
|
85
|
+
const originalHeaders = {};
|
|
86
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
87
|
+
originalHeaders[key] = Array.isArray(value) ? value.join(', ') : value;
|
|
88
|
+
}
|
|
89
|
+
// Filter and transform headers
|
|
90
|
+
const filteredHeaders = this.filterHeaders(originalHeaders);
|
|
91
|
+
const finalHeaders = options.headers ? options.headers(filteredHeaders) : filteredHeaders;
|
|
92
|
+
// Process cookies
|
|
93
|
+
const finalCookies = this.processCookies(req, options.cookies);
|
|
94
|
+
// Build proxy headers
|
|
95
|
+
const headersWithoutCookie = this.convertHeadersToRecord(finalHeaders);
|
|
96
|
+
const forwardedHeaders = this.buildForwardedHeaders(req, targetHost);
|
|
97
|
+
const proxyHeaders = {
|
|
98
|
+
...headersWithoutCookie,
|
|
99
|
+
...forwardedHeaders,
|
|
100
|
+
};
|
|
101
|
+
if (finalCookies.length > 0) {
|
|
102
|
+
proxyHeaders.Cookie = finalCookies.join('; ');
|
|
103
|
+
}
|
|
104
|
+
return { proxyHeaders, finalCookies };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Filters hop-by-hop headers from response headers
|
|
108
|
+
*/
|
|
109
|
+
isHopByHopHeader(headerName) {
|
|
110
|
+
return HOP_BY_HOP_HEADERS.has(headerName.toLowerCase());
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=header-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-processor.js","sourceRoot":"","sources":["../src/header-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-processor.spec.d.ts","sourceRoot":"","sources":["../src/header-processor.spec.ts"],"names":[],"mappings":""}
|