mikser-io 9.0.5 → 9.1.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/docs/plugins.md +13 -0
- package/package.json +1 -1
- package/src/plugins/api.js +18 -1
package/docs/plugins.md
CHANGED
|
@@ -681,6 +681,7 @@ api: {
|
|
|
681
681
|
base: '/api', // mount prefix; default '/api'
|
|
682
682
|
pageSize: 10, // global default; per-endpoint override below
|
|
683
683
|
renderTimeout: 30_000, // global default; per-endpoint override below
|
|
684
|
+
bodyLimit: '2mb', // global default; per-endpoint override below
|
|
684
685
|
endpoints: {
|
|
685
686
|
public: {
|
|
686
687
|
// No token → publicly readable. The query function scopes what
|
|
@@ -706,11 +707,23 @@ api: {
|
|
|
706
707
|
token: process.env.API_RENDER_TOKEN,
|
|
707
708
|
operations: ['render'],
|
|
708
709
|
renderTimeout: 60_000,
|
|
710
|
+
bodyLimit: '8mb', // override the global bodyLimit
|
|
709
711
|
},
|
|
710
712
|
},
|
|
711
713
|
}
|
|
712
714
|
```
|
|
713
715
|
|
|
716
|
+
**`bodyLimit`** is worth setting deliberately on a `render` endpoint. The request
|
|
717
|
+
body carries the whole entity, so its size is the size of everything the layout
|
|
718
|
+
needs — a mail template handed a customer's recent history is easily several
|
|
719
|
+
hundred kilobytes, which is not large but is well past Express's 100kb default.
|
|
720
|
+
|
|
721
|
+
The failure mode argues for getting this right rather than discovering it: the
|
|
722
|
+
body is rejected while the stream is being read, so the render never runs, the
|
|
723
|
+
rejection is not logged as a render error, and the caller receives an HTML error
|
|
724
|
+
page from a JSON API. It reads as "the thing I was rendering for is broken",
|
|
725
|
+
not as "the request was too big".
|
|
726
|
+
|
|
714
727
|
**Routes per endpoint:**
|
|
715
728
|
|
|
716
729
|
| Method | Path | Operation | Description |
|
package/package.json
CHANGED
package/src/plugins/api.js
CHANGED
|
@@ -359,6 +359,23 @@ export function api(options = {}) {
|
|
|
359
359
|
const base = apiBase // alias so existing local references still work
|
|
360
360
|
const globalPageSize = options.pageSize ?? 10
|
|
361
361
|
const globalRenderTimeout = options.renderTimeout ?? 30_000
|
|
362
|
+
// express.json() defaults to 100kb, which is a sensible ceiling for a
|
|
363
|
+
// REST body and much too small for `render`: the caller posts an entity
|
|
364
|
+
// whose meta carries everything the layout needs, and a mail template
|
|
365
|
+
// given a list of a customer's recent bookings runs 150–400kb. That
|
|
366
|
+
// exceeds the default without being remotely large.
|
|
367
|
+
//
|
|
368
|
+
// The failure is quiet at the wrong end. The renderer never sees the
|
|
369
|
+
// request — raw-body rejects it while reading the stream — so nothing
|
|
370
|
+
// appears in mikser's log, and the caller gets an HTML error page for a
|
|
371
|
+
// JSON API. On gpoint that was 168 renders lost in under two hours,
|
|
372
|
+
// including the customer booking confirmations, and it looked from the
|
|
373
|
+
// outside like the mail was broken rather than the render.
|
|
374
|
+
//
|
|
375
|
+
// 2mb, and configurable per endpoint like every other limit here. Not
|
|
376
|
+
// unbounded: a token-gated endpoint is still a body an attacker can
|
|
377
|
+
// choose the size of.
|
|
378
|
+
const globalBodyLimit = options.bodyLimit ?? '2mb'
|
|
362
379
|
|
|
363
380
|
// Preview workflow (render → cache → URL) lives in its own
|
|
364
381
|
// plugin (src/plugins/preview.js) as of v7.3.0. The api plugin
|
|
@@ -377,7 +394,7 @@ export function api(options = {}) {
|
|
|
377
394
|
// api.endpoints.admin { token: '...', operations: ['list','update','delete','render'] }
|
|
378
395
|
for (const [name, ep] of Object.entries(endpoints)) {
|
|
379
396
|
const router = express.Router()
|
|
380
|
-
router.use(express.json())
|
|
397
|
+
router.use(express.json({ limit: ep.bodyLimit ?? globalBodyLimit }))
|
|
381
398
|
|
|
382
399
|
// Operations default to the safer shape when no token is set
|
|
383
400
|
// (read-only) and full access when token-gated. `subscribe`
|