@forestadmin/agent-bff 1.29.0 → 1.30.0
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 +115 -8
- package/dist/build-bff.js +3 -1
- package/dist/http/access-log-middleware.d.ts +26 -0
- package/dist/http/access-log-middleware.js +68 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,9 @@ dropped collection reachable.
|
|
|
33
33
|
|
|
34
34
|
## Usage
|
|
35
35
|
|
|
36
|
+
Two ways to run it: embedded in a Forest agent (`agent.addBff()`, see
|
|
37
|
+
[Embedded in an agent](#embedded-in-an-agent)) or standalone, described here.
|
|
38
|
+
|
|
36
39
|
Packaged / production — run the bin:
|
|
37
40
|
|
|
38
41
|
```bash
|
|
@@ -159,9 +162,12 @@ Two layers, both driven by exact-origin matching (case-insensitive scheme/host,
|
|
|
159
162
|
normalized away, no trailing slash, no wildcard, no subdomain matching):
|
|
160
163
|
|
|
161
164
|
- **Layer 1 (transport)** — the only layer that sets `Access-Control-Allow-Origin`. An origin in
|
|
162
|
-
`BFF_ALLOWED_ORIGINS` is echoed back exactly;
|
|
163
|
-
|
|
164
|
-
the
|
|
165
|
+
`BFF_ALLOWED_ORIGINS` is echoed back exactly; any other `Origin` is refused outright with
|
|
166
|
+
`403 origin_not_allowed`, rather than served without the header and left for the browser to
|
|
167
|
+
discard — omitting the header only stops the caller from *reading* the answer, and the request
|
|
168
|
+
would already have run. A request with no `Origin` at all is untouched, which is every
|
|
169
|
+
server-to-server api-key call. Applies to `POST /oauth/token` too. Preflight `OPTIONS` from an
|
|
170
|
+
allow-listed origin gets the allowed methods + headers; credentials are never enabled.
|
|
165
171
|
- **Layer 2 (per-key authorization, Mode 2 only)** — when the resolved key has a non-empty
|
|
166
172
|
`allowedOrigins`, an `Origin` sent by the client must be in that list, else
|
|
167
173
|
`403 origin_not_allowed`. A request with no `Origin` at all — a server-side client such as curl,
|
|
@@ -230,11 +236,112 @@ with `session_expired`. Horizontal scaling requires both a shared session store
|
|
|
230
236
|
|
|
231
237
|
```jsonc
|
|
232
238
|
// 200 — all required config present
|
|
233
|
-
{
|
|
239
|
+
{
|
|
240
|
+
"status": "ok",
|
|
241
|
+
"version": "<package version>",
|
|
242
|
+
"configured": { "oauth": true, "ai": true, "cors": true, "openapi": true }
|
|
243
|
+
}
|
|
234
244
|
// 503 — one or more required keys missing
|
|
235
|
-
{ "status": "degraded", "version": "<package version>" }
|
|
245
|
+
{ "status": "degraded", "version": "<package version>", "configured": { /* … */ } }
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`configured` says which optional surfaces this deployment was set up to serve — deliberately not
|
|
249
|
+
that they work: `oauth` is `true` as soon as a key is set, whether or not the Forest server ever
|
|
250
|
+
answers. They form a chain, not four independent switches:
|
|
251
|
+
|
|
252
|
+
| Surface | Switched on by |
|
|
253
|
+
| --- | --- |
|
|
254
|
+
| `oauth` | `BFF_TOKEN_ENCRYPTION_KEY` **and** `FOREST_SERVER_URL`, `FOREST_ENV_SECRET`, `FOREST_APP_URL`, `FOREST_AUTH_SECRET` — the routes need a Forest server to talk to as much as a key. Embedded, only `tokenEncryptionKey` is yours to set: the other four are inherited |
|
|
255
|
+
| `ai` | `oauth` — the relay needs a session, and only the OAuth flow creates one |
|
|
256
|
+
| `cors` | a non-empty `BFF_ALLOWED_ORIGINS` (`allowedOrigins`) |
|
|
257
|
+
| `openapi` | `BFF_OPENAPI_ENABLED` (`openapiEnabled`), and a mounted agent edge |
|
|
258
|
+
|
|
259
|
+
The body still never discloses which config *keys* are present or missing — that would leak the
|
|
260
|
+
internal config surface to an unauthenticated probe. It names the surfaces, never the values behind
|
|
261
|
+
them. Missing keys are logged once at startup (`Warn`) for operators. Every response the BFF
|
|
262
|
+
itself produces carries the `X-Forest-Bff-Version` header, read from `package.json`. The one
|
|
263
|
+
exception is the embedded `503 bff_not_started` / `bff_stopped` below: the agent writes those
|
|
264
|
+
itself, with no BFF to read a version from.
|
|
265
|
+
|
|
266
|
+
## Embedded in an agent
|
|
267
|
+
|
|
268
|
+
The same BFF runs inside a Forest agent, with no second deployment and no second port:
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
await createAgent(options)
|
|
272
|
+
.addDataSource(/* … */)
|
|
273
|
+
.addBff({ allowedOrigins: ['https://my-app.com'] })
|
|
274
|
+
.mountOnStandaloneServer(3351)
|
|
275
|
+
.start();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
A mount is what opens a socket — `start()` only builds the agent's router, so without a
|
|
279
|
+
`mountOn*` call nothing is served, BFF included.
|
|
280
|
+
|
|
281
|
+
It answers under `/bff` on whatever port the agent is mounted on — `/bff/agent/v1/{collection}/list`,
|
|
282
|
+
`/bff/health`, `/bff/oauth/*` — so the REST contract is the one documented above and only the base
|
|
283
|
+
url changes.
|
|
284
|
+
|
|
285
|
+
A host serving the agent under a sub-path of its own is supported: `app.use('/api', mounted)` puts
|
|
286
|
+
the BFF at `/api/bff`, and the emitted prefix is derived per request from `originalUrl`
|
|
287
|
+
(`base-path.ts`), so the `servers` entry and the docs page carry `/api/bff` rather than the
|
|
288
|
+
configured `/bff`.
|
|
289
|
+
|
|
290
|
+
The *served* OpenAPI document carries the prefix in its `servers` entry, so a client generated from
|
|
291
|
+
`GET /bff/agent/openapi.json` is correct as-is. The *exported* one does not: `forest-bff openapi`
|
|
292
|
+
has no way to be told about a prefix and always emits `servers: [{ "url": "/" }]`. Generating a
|
|
293
|
+
client from the export against an embedded BFF means pointing its base url at `/bff` yourself.
|
|
294
|
+
|
|
295
|
+
What differs from the standalone deployment:
|
|
296
|
+
|
|
297
|
+
| | Standalone | Embedded |
|
|
298
|
+
| --- | --- | --- |
|
|
299
|
+
| Configuration | environment variables | `addBff()` options; the secrets, the Forest urls and the logger are inherited from the agent and cannot be overridden |
|
|
300
|
+
| `AGENT_URL` | required, an http(s) url | gone — the BFF reaches the agent in the same process, without a socket |
|
|
301
|
+
| `HTTP_PORT` | its own listener | gone — the agent's port serves it |
|
|
302
|
+
| `openapiEnabled` | `true` | `false`. The document is not filtered per caller, so adding a BFF must not silently publish every collection and field name on an already-open port |
|
|
303
|
+
| `/health` | 503 until every required key is set | always 200: an in-process dispatcher short-circuits the readiness check, since a 503 here would let a load balancer restart a process that serves api-key traffic fine. It stays 200 with no `tokenEncryptionKey`, which is *not* inherited — read `configured` to know what is on |
|
|
304
|
+
|
|
305
|
+
**Registration order matters on Express and Connect-style hosts.** Mount the agent *before* any
|
|
306
|
+
body parser of your own:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
const app = express();
|
|
310
|
+
agent.mountOnExpress(app); // first
|
|
311
|
+
app.use(express.json()); // then yours
|
|
312
|
+
await agent.start();
|
|
236
313
|
```
|
|
237
314
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
315
|
+
A body parser that runs first has already consumed the request stream, and nothing downstream can
|
|
316
|
+
put it back: every BFF `POST` then answers `500 stream.not.readable`.
|
|
317
|
+
|
|
318
|
+
A permissive `cors()` registered ahead of the mount costs the preflight, not the allow-list. The
|
|
319
|
+
host answers `OPTIONS` with its own policy and that is unrecoverable, but the request that follows
|
|
320
|
+
still reaches this app, where an `Origin` outside `BFF_ALLOWED_ORIGINS` is refused with
|
|
321
|
+
`403 origin_not_allowed` — the browser reads the wrong preflight, and the collection is still never
|
|
322
|
+
read for that origin. A caller sending no `Origin` at all is untouched, which is every
|
|
323
|
+
server-to-server api-key call.
|
|
324
|
+
|
|
325
|
+
NestJS needs no special handling as long as you mount before `listen()`: `NestFactory.create()`
|
|
326
|
+
does not install its body parser, `init()` does, and `listen()` is what triggers `init()` — so the
|
|
327
|
+
middleware `mountOnNestJs()` registers is already ahead of it.
|
|
328
|
+
|
|
329
|
+
**`/bff/*` answers `503` while the BFF is not serving**, and the two ends of the lifecycle are told
|
|
330
|
+
apart: `bff_not_started` between `addBff()` and the end of `start()`, `bff_stopped` after `stop()`.
|
|
331
|
+
The agent claims the prefix as soon as it is mounted, and a 404 there would read as "wrong url"
|
|
332
|
+
rather than "not available". A probe should wait on the first and drain on the second.
|
|
333
|
+
|
|
334
|
+
**`addBff()` and `mountAiMcpServer({ basePath: '/bff' })` are mutually exclusive** — whichever is
|
|
335
|
+
called second throws on the spot, at the builder call and not from `start()`, rather than letting
|
|
336
|
+
the MCP server quietly claim `/bff/oauth` and `/bff/mcp`. Any `basePath` landing inside `/bff`
|
|
337
|
+
counts (`bff`, `/bff/`, `/bff/ai`), so mount the MCP server elsewhere.
|
|
338
|
+
|
|
339
|
+
**One security control does not apply to the embedded mode.** If the environment has Forest's IP
|
|
340
|
+
whitelist enabled, requests served under `/bff` are not subject to it: they reach the agent
|
|
341
|
+
in-process, over what the whitelist treats as a trusted loopback caller. This is deliberate —
|
|
342
|
+
applying it would filter the browsers a third-party UI is made of, and the standalone deployment
|
|
343
|
+
never filtered the end user either, only the BFF's own host. A resolved API key or a valid OAuth
|
|
344
|
+
session is still required, and the agent still logs a warning at startup naming the exemption.
|
|
345
|
+
|
|
346
|
+
When to prefer which: embedded for a single deployment, which is most of them. Standalone when
|
|
347
|
+
several agents share one BFF, or when the BFF and the agent have to scale separately.
|
package/dist/build-bff.js
CHANGED
|
@@ -60,6 +60,7 @@ const cors_middleware_1 = __importDefault(require("./cors/cors-middleware"));
|
|
|
60
60
|
const per_key_origin_1 = __importDefault(require("./cors/per-key-origin"));
|
|
61
61
|
const data_routes_middleware_1 = __importDefault(require("./data/data-routes-middleware"));
|
|
62
62
|
const docs_routes_1 = __importDefault(require("./docs/docs-routes"));
|
|
63
|
+
const access_log_middleware_1 = __importDefault(require("./http/access-log-middleware"));
|
|
63
64
|
const bff_http_error_1 = require("./http/bff-http-error");
|
|
64
65
|
const body_limit_1 = __importStar(require("./http/body-limit"));
|
|
65
66
|
const error_middleware_1 = __importDefault(require("./http/error-middleware"));
|
|
@@ -372,6 +373,7 @@ async function buildBff({ config, logger = (0, console_logger_1.default)(), base
|
|
|
372
373
|
const agentErrorMiddleware = hasAgentEdge ? [agentScoped((0, error_middleware_1.default)({ logger }))] : [];
|
|
373
374
|
const agentJsonOnlyGuard = hasAgentEdge ? [agentScoped(createJsonOnlyGuard())] : [];
|
|
374
375
|
const middlewares = [
|
|
376
|
+
(0, access_log_middleware_1.default)({ logger, basePath: mountPath }),
|
|
375
377
|
(0, version_header_middleware_1.default)(version_1.default),
|
|
376
378
|
(0, health_route_1.default)({
|
|
377
379
|
version: version_1.default,
|
|
@@ -408,4 +410,4 @@ async function buildBff({ config, logger = (0, console_logger_1.default)(), base
|
|
|
408
410
|
app.use(middleware);
|
|
409
411
|
return { callback: app.callback(), invalidate: agentEdge.invalidate };
|
|
410
412
|
}
|
|
411
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtYmZmLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2J1aWxkLWJmZi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9LQSxnREFlQztBQWdLRCxrREFNQztBQW1KRCwyQkFpRkM7QUFqakJELGdEQUE2QztBQUM3Qyw4Q0FBc0I7QUFFdEIsaUdBQTZFO0FBQzdFLCtFQUE0RDtBQUM1RCxvRUFBMkQ7QUFDM0QsNkRBQThEO0FBQzlELHdGQUFvRTtBQUNwRSwyRUFBaUQ7QUFDakQsa0ZBQXFGO0FBQ3JGLDRGQUF3RTtBQUN4RSw4RUFBb0Q7QUFDcEQsc0ZBQWtFO0FBQ2xFLDRFQUF5RDtBQUN6RCx1RkFBbUU7QUFDbkUsNERBQTRDO0FBQzVDLDZGQUFnRTtBQUNoRSxvR0FBZ0Y7QUFDaEYsNkVBQTBEO0FBQzFELDJFQUFpRTtBQUNqRSwyRkFBdUU7QUFDdkUscUVBQWtEO0FBQ2xELDBEQUEyRTtBQUMzRSxnRUFBOEQ7QUFDOUQsK0VBQTREO0FBQzVELHVFQUFvRDtBQUNwRCxpR0FBNkU7QUFDN0UseUVBQW1HO0FBQ25HLHdGQUE4RDtBQUM5RCx3RUFBcUQ7QUFDckQsMEVBQStEO0FBQy9ELHdFQUFxRDtBQUNyRCwyRUFBNkU7QUFDN0Usd0ZBQStEO0FBQy9ELDBGQUFpRTtBQUNqRSxnSEFBNEY7QUFDNUYseUVBQWtEO0FBQ2xELCtGQUEyRTtBQUMzRSx1RkFBNkQ7QUFDN0QseUZBQXNFO0FBQ3RFLHdEQUFnQztBQXNDaEMsTUFBTSxtQkFBbUIsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUV6QyxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUV2RCxNQUFNLGVBQWUsR0FBRyxDQUFDLGtCQUFrQixFQUFFLG9CQUFvQixDQUFDLENBQUM7QUFFbkUs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
|
|
413
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtYmZmLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2J1aWxkLWJmZi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXFLQSxnREFlQztBQWdLRCxrREFNQztBQW1KRCwyQkFrRkM7QUFuakJELGdEQUE2QztBQUM3Qyw4Q0FBc0I7QUFFdEIsaUdBQTZFO0FBQzdFLCtFQUE0RDtBQUM1RCxvRUFBMkQ7QUFDM0QsNkRBQThEO0FBQzlELHdGQUFvRTtBQUNwRSwyRUFBaUQ7QUFDakQsa0ZBQXFGO0FBQ3JGLDRGQUF3RTtBQUN4RSw4RUFBb0Q7QUFDcEQsc0ZBQWtFO0FBQ2xFLDRFQUF5RDtBQUN6RCx1RkFBbUU7QUFDbkUsNERBQTRDO0FBQzVDLDZGQUFnRTtBQUNoRSxvR0FBZ0Y7QUFDaEYsNkVBQTBEO0FBQzFELDJFQUFpRTtBQUNqRSwyRkFBdUU7QUFDdkUscUVBQWtEO0FBQ2xELHlGQUFxRTtBQUNyRSwwREFBMkU7QUFDM0UsZ0VBQThEO0FBQzlELCtFQUE0RDtBQUM1RCx1RUFBb0Q7QUFDcEQsaUdBQTZFO0FBQzdFLHlFQUFtRztBQUNuRyx3RkFBOEQ7QUFDOUQsd0VBQXFEO0FBQ3JELDBFQUErRDtBQUMvRCx3RUFBcUQ7QUFDckQsMkVBQTZFO0FBQzdFLHdGQUErRDtBQUMvRCwwRkFBaUU7QUFDakUsZ0hBQTRGO0FBQzVGLHlFQUFrRDtBQUNsRCwrRkFBMkU7QUFDM0UsdUZBQTZEO0FBQzdELHlGQUFzRTtBQUN0RSx3REFBZ0M7QUFzQ2hDLE1BQU0sbUJBQW1CLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFekMsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFFdkQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxrQkFBa0IsRUFBRSxvQkFBb0IsQ0FB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
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Logger } from '../ports/logger-port';
|
|
2
|
+
import type { Middleware } from 'koa';
|
|
3
|
+
export interface AccessLogMiddlewareOptions {
|
|
4
|
+
logger: Logger;
|
|
5
|
+
/** Prefix the host serves this BFF under, so the line names a url the caller can actually call. */
|
|
6
|
+
basePath: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* One line per request, in the shape the agent's own request logger emits (`[200] GET /path - 12ms`)
|
|
10
|
+
* so both layers read the same way in an embedded deployment.
|
|
11
|
+
*
|
|
12
|
+
* Belongs at the head of the chain: everything below it — `/health`, `/docs`, `/oauth/*`, a 401 from
|
|
13
|
+
* the auth edge, a rejected origin — either never reaches the agent or never reaches the
|
|
14
|
+
* agent-scoped error middleware, and is exactly the traffic that used to leave no trace at all.
|
|
15
|
+
*
|
|
16
|
+
* The query string is deliberately absent. Nothing routed today needs it, and a line that carries it
|
|
17
|
+
* would leak whatever a future route accepts there without anyone revisiting this decision.
|
|
18
|
+
*
|
|
19
|
+
* Carries no cause either, so that a host logger which cannot take structured fields still reads as
|
|
20
|
+
* one line per request. The detail is not lost where it matters: `createErrorMiddleware` already
|
|
21
|
+
* reports it for everything under `/agent`. Outside it — a body parser rejection on an OAuth POST is
|
|
22
|
+
* the only route there today — the stack reaches stderr through Koa's own handler, as it did before
|
|
23
|
+
* this middleware existed.
|
|
24
|
+
*/
|
|
25
|
+
export default function createAccessLogMiddleware({ logger, basePath, }: AccessLogMiddlewareOptions): Middleware;
|
|
26
|
+
//# sourceMappingURL=access-log-middleware.d.ts.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = createAccessLogMiddleware;
|
|
4
|
+
const base_path_1 = require("../base-path");
|
|
5
|
+
const CLIENT_ERROR = 400;
|
|
6
|
+
const SERVER_ERROR = 500;
|
|
7
|
+
function levelOf(status) {
|
|
8
|
+
if (status >= SERVER_ERROR)
|
|
9
|
+
return 'Error';
|
|
10
|
+
if (status >= CLIENT_ERROR)
|
|
11
|
+
return 'Warn';
|
|
12
|
+
return 'Info';
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The status the caller will see, read off an exception rather than off the response: this
|
|
16
|
+
* middleware sits above every error handler the BFF has, so at the moment it logs, `ctx.status` is
|
|
17
|
+
* still the 404 Koa defaults to and would name a status nobody was ever answered.
|
|
18
|
+
*/
|
|
19
|
+
function statusOf(error) {
|
|
20
|
+
if (typeof error !== 'object' || error === null)
|
|
21
|
+
return SERVER_ERROR;
|
|
22
|
+
const { status, statusCode } = error;
|
|
23
|
+
const value = typeof status === 'number' ? status : statusCode;
|
|
24
|
+
return typeof value === 'number' ? value : SERVER_ERROR;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* One line per request, in the shape the agent's own request logger emits (`[200] GET /path - 12ms`)
|
|
28
|
+
* so both layers read the same way in an embedded deployment.
|
|
29
|
+
*
|
|
30
|
+
* Belongs at the head of the chain: everything below it — `/health`, `/docs`, `/oauth/*`, a 401 from
|
|
31
|
+
* the auth edge, a rejected origin — either never reaches the agent or never reaches the
|
|
32
|
+
* agent-scoped error middleware, and is exactly the traffic that used to leave no trace at all.
|
|
33
|
+
*
|
|
34
|
+
* The query string is deliberately absent. Nothing routed today needs it, and a line that carries it
|
|
35
|
+
* would leak whatever a future route accepts there without anyone revisiting this decision.
|
|
36
|
+
*
|
|
37
|
+
* Carries no cause either, so that a host logger which cannot take structured fields still reads as
|
|
38
|
+
* one line per request. The detail is not lost where it matters: `createErrorMiddleware` already
|
|
39
|
+
* reports it for everything under `/agent`. Outside it — a body parser rejection on an OAuth POST is
|
|
40
|
+
* the only route there today — the stack reaches stderr through Koa's own handler, as it did before
|
|
41
|
+
* this middleware existed.
|
|
42
|
+
*/
|
|
43
|
+
function createAccessLogMiddleware({ logger, basePath, }) {
|
|
44
|
+
return async function accessLog(ctx, next) {
|
|
45
|
+
const startedAt = Date.now();
|
|
46
|
+
const write = (status) => {
|
|
47
|
+
const path = `${(0, base_path_1.emittedBaseOf)(ctx, basePath)}${ctx.path}`;
|
|
48
|
+
try {
|
|
49
|
+
logger(levelOf(status), `[${status}] ${ctx.method} ${path} - ${Date.now() - startedAt}ms`);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// The logger belongs to the host and nothing in the port forbids it from throwing. Left
|
|
53
|
+
// unguarded, a throw here would answer 500 to a request the route served, and on the error
|
|
54
|
+
// path it would replace the exception being reported with its own. There is nowhere to
|
|
55
|
+
// report this: the only sink available is the logger that just failed.
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
await next();
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
write(statusOf(error));
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
write(ctx.response.status);
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjZXNzLWxvZy1taWRkbGV3YXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2h0dHAvYWNjZXNzLWxvZy1taWRkbGV3YXJlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBb0RBLDRDQThCQztBQS9FRCw0Q0FBNkM7QUFRN0MsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDO0FBQ3pCLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUV6QixTQUFTLE9BQU8sQ0FBQyxNQUFjO0lBQzdCLElBQUksTUFBTSxJQUFJLFlBQVk7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUMzQyxJQUFJLE1BQU0sSUFBSSxZQUFZO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFFMUMsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLFFBQVEsQ0FBQyxLQUFjO0lBQzlCLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJO1FBQUUsT0FBTyxZQUFZLENBQUM7SUFFckUsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxLQUFtRCxDQUFDO0lBQ25GLE1BQU0sS0FBSyxHQUFHLE9BQU8sTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7SUFFL0QsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO0FBQzFELENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILFNBQXdCLHlCQUF5QixDQUFDLEVBQ2hELE1BQU0sRUFDTixRQUFRLEdBQ21CO0lBQzNCLE9BQU8sS0FBSyxVQUFVLFNBQVMsQ0FBQyxHQUFHLEVBQUUsSUFBSTtRQUN2QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFFN0IsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFjLEVBQUUsRUFBRTtZQUMvQixNQUFNLElBQUksR0FBRyxHQUFHLElBQUEseUJBQWEsRUFBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO1lBRTFELElBQUksQ0FBQztnQkFDSCxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLElBQUksSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLElBQUksQ0FBQyxDQUFDO1lBQzdGLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1Asd0ZBQXdGO2dCQUN4RiwyRkFBMkY7Z0JBQzNGLHVGQUF1RjtnQkFDdkYsdUVBQXVFO1lBQ3pFLENBQUM7UUFDSCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ2YsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFFdkIsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO1FBRUQsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0IsQ0FBQyxDQUFDO0FBQ0osQ0FBQyJ9
|