[{"data":1,"prerenderedAt":785},["ShallowReactive",2],{"navigation":3,"-guide-body-limit":61,"-guide-body-limit-surround":780},[4],{"title":5,"path":6,"stem":7,"children":8,"icon":10},"Getting Started","/guide","1.guide/01.index",[9,11,16,21,26,31,36,41,46,51,56],{"title":5,"path":6,"stem":7,"icon":10},"ph:book-open-duotone",{"title":12,"path":13,"stem":14,"icon":15},"Fetch Handler","/guide/handler","1.guide/02.handler","i-fluent:target-24-regular",{"title":17,"path":18,"stem":19,"icon":20},"Server Instance","/guide/server","1.guide/03.server","radix-icons:component-instance",{"title":22,"path":23,"stem":24,"icon":25},"Middleware","/guide/middleware","1.guide/04.middleware","clarity:plugin-line",{"title":27,"path":28,"stem":29,"icon":30},"Server Options","/guide/options","1.guide/05.options","ri:settings-3-line",{"title":32,"path":33,"stem":34,"icon":35},"TLS","/guide/tls","1.guide/06.tls","ri:lock-2-line",{"title":37,"path":38,"stem":39,"icon":40},"Bundler Usage","/guide/bundler","1.guide/07.bundler","clarity:bundle-line",{"title":42,"path":43,"stem":44,"icon":45},"Node.js Support","/guide/node","1.guide/08.node","akar-icons:node-fill",{"title":47,"path":48,"stem":49,"icon":50},"Using CLI","/guide/cli","1.guide/10.cli","garden:terminal-cli-stroke-12",{"title":52,"path":53,"stem":54,"icon":55},"Body Size Limiting","/guide/body-limit","1.guide/11.body-limit","ri:scales-3-line",{"title":57,"path":58,"stem":59,"icon":60},"AWS Lambda","/guide/aws-lambda","1.guide/9.aws-lambda","clarity:cloud-traffic-line",{"id":62,"title":52,"body":63,"description":774,"extension":775,"meta":776,"navigation":777,"path":53,"seo":778,"stem":54,"__hash__":779},"content/1.guide/11.body-limit.md",{"type":64,"value":65,"toc":768,"icon":55},"minimark",[66,88,91,104,111,118,193,208,214,247,278,352,379,390,394,409,462,636,640,661,753,764],[67,68,69,70,78,79,82,83,87],"p",{},"The ",[71,72,74],"a",{"href":73},"/guide/options#maxrequestbodysize",[75,76,77],"code",{},"maxRequestBodySize"," option enforces a body size limit for the whole server. The same building blocks are exported from ",[75,80,81],{},"srvx/body-limit"," so downstream layers (for example per-route or per-handler limits) can enforce the ",[84,85,86],"strong",{},"same streaming semantics and error shape"," without re-implementing them.",[67,89,90],{},"These helpers use only web streams (no Node.js APIs), so they run on any runtime.",[92,93,94],"note",{},[67,95,96,97,99,100,103],{},"\nOn Bun the server-level ",[75,98,77],{}," is enforced natively by ",[75,101,102],{},"Bun.serve",". These helpers still work anywhere for your own limits, but the srvx Node and Deno adapters are the ones that use them internally.",[105,106,108],"h2",{"id":107},"limitbodystream",[75,109,110],{},"limitBodyStream",[67,112,113,114,117],{},"Wraps a body ",[75,115,116],{},"ReadableStream\u003CUint8Array>"," so the total number of bytes read cannot exceed the limit, returning a new stream.",[119,120,125],"pre",{"className":121,"code":122,"language":123,"meta":124,"style":124},"language-js shiki shiki-themes github-light github-dark github-dark","import { limitBodyStream } from \"srvx/body-limit\";\n\nconst limited = limitBodyStream(request.body, 1024 * 1024 /* 1 MiB */);\n","js","",[75,126,127,150,157],{"__ignoreMap":124},[128,129,132,136,140,143,147],"span",{"class":130,"line":131},"line",1,[128,133,135],{"class":134},"so5gQ","import",[128,137,139],{"class":138},"slsVL"," { limitBodyStream } ",[128,141,142],{"class":134},"from",[128,144,146],{"class":145},"sfrk1"," \"srvx/body-limit\"",[128,148,149],{"class":138},";\n",[128,151,153],{"class":130,"line":152},2,[128,154,156],{"emptyLinePlaceholder":155},true,"\n",[128,158,160,163,167,170,174,177,180,183,186,190],{"class":130,"line":159},3,[128,161,162],{"class":134},"const",[128,164,166],{"class":165},"suiK_"," limited",[128,168,169],{"class":134}," =",[128,171,173],{"class":172},"shcOC"," limitBodyStream",[128,175,176],{"class":138},"(request.body, ",[128,178,179],{"class":165},"1024",[128,181,182],{"class":134}," *",[128,184,185],{"class":165}," 1024",[128,187,189],{"class":188},"sCsY4"," /* 1 MiB */",[128,191,192],{"class":138},");\n",[67,194,195,196,199,200,207],{},"It is ",[84,197,198],{},"pull-based",": it reads from the upstream stream only when the consumer pulls, so it preserves backpressure and never buffers the whole body. As soon as the accumulated size passes the limit, the wrapped stream errors with a ",[71,201,203,206],{"href":202},"#error-shape",[75,204,205],{},"413","-style error"," and the upstream stream is cancelled with that same error, so the source can stop producing and release the socket. Cancelling the wrapped stream propagates the cancellation upstream.",[105,209,211],{"id":210},"limitrequestbody",[75,212,213],{},"limitRequestBody",[67,215,216,217,220,221,224,225,224,228,224,231,224,234,224,237,224,240,224,243,246],{},"Returns a request whose body is size-limited. A request without a body is returned unchanged; otherwise it is wrapped in a ",[75,218,219],{},"Proxy"," that routes every body read (",[75,222,223],{},"body"," / ",[75,226,227],{},"text",[75,229,230],{},"json",[75,232,233],{},"formData",[75,235,236],{},"arrayBuffer",[75,238,239],{},"blob",[75,241,242],{},"bytes",[75,244,245],{},"bodyUsed",") through a single size-limited stream and passes everything else through to the original request.",[67,248,249,250,253,254,260,261,263,264,267,268,267,271,267,274,277],{},"Because it wraps rather than rebuilds, the returned value is the ",[84,251,252],{},"same type"," as the input and keeps its identity: a ",[71,255,257],{"href":256},"/guide/handler#extended-request-serverrequest",[75,258,259],{},"ServerRequest"," stays a ",[75,262,259],{},", with its augmentation (",[75,265,266],{},"runtime",", ",[75,269,270],{},"waitUntil",[75,272,273],{},"ip",[75,275,276],{},"context",", …) intact.",[119,279,281],{"className":121,"code":280,"language":123,"meta":124,"style":124},"import { limitRequestBody } from \"srvx/body-limit\";\n\nconst safeRequest = limitRequestBody(request, 1024 * 1024 /* 1 MiB */);\n// reading the body throws the 413-style error if it exceeds the limit\nconst data = await safeRequest.json();\n",[75,282,283,296,300,325,331],{"__ignoreMap":124},[128,284,285,287,290,292,294],{"class":130,"line":131},[128,286,135],{"class":134},[128,288,289],{"class":138}," { limitRequestBody } ",[128,291,142],{"class":134},[128,293,146],{"class":145},[128,295,149],{"class":138},[128,297,298],{"class":130,"line":152},[128,299,156],{"emptyLinePlaceholder":155},[128,301,302,304,307,309,312,315,317,319,321,323],{"class":130,"line":159},[128,303,162],{"class":134},[128,305,306],{"class":165}," safeRequest",[128,308,169],{"class":134},[128,310,311],{"class":172}," limitRequestBody",[128,313,314],{"class":138},"(request, ",[128,316,179],{"class":165},[128,318,182],{"class":134},[128,320,185],{"class":165},[128,322,189],{"class":188},[128,324,192],{"class":138},[128,326,328],{"class":130,"line":327},4,[128,329,330],{"class":188},"// reading the body throws the 413-style error if it exceeds the limit\n",[128,332,334,336,339,341,344,347,349],{"class":130,"line":333},5,[128,335,162],{"class":134},[128,337,338],{"class":165}," data",[128,340,169],{"class":134},[128,342,343],{"class":134}," await",[128,345,346],{"class":138}," safeRequest.",[128,348,230],{"class":172},[128,350,351],{"class":138},"();\n",[67,353,354,355,358,359,362,363,365,366,224,369,224,372,224,375,378],{},"When the request declares a ",[75,356,357],{},"Content-Length"," that already exceeds the limit, the body is ",[84,360,361],{},"rejected early",": the original body is cancelled without being read and the returned request's body errors immediately. ",[75,364,357],{}," is only a fast path — it may be absent (chunked transfer encoding) or understated, so the streaming limit is always enforced regardless. The error surfaces when the body is consumed (",[75,367,368],{},"request.text()",[75,370,371],{},".json()",[75,373,374],{},".arrayBuffer()",[75,376,377],{},".body","), matching the streamed-limit behaviour.",[92,380,381],{},[67,382,383,384,386,387,389],{},"\nA request whose ",[75,385,357],{}," overstates the actual body (e.g. it declares more bytes than it sends) is rejected on the declared length, even if the bytes that follow would fit — an overstated ",[75,388,357],{}," is a malformed request, and this matches how servers such as Bun and nginx enforce their limits.",[105,391,393],{"id":392},"error-shape","Error shape",[67,395,396,397,400,401,404,405,408],{},"Both helpers reject with the canonical error created by ",[75,398,399],{},"createBodyTooLargeError"," (typed as the exported ",[75,402,403],{},"BodyTooLargeError","). It carries a stable, documented shape so any layer can map it to an HTTP ",[75,406,407],{},"413 Payload Too Large"," response without string matching:",[410,411,412,425],"table",{},[413,414,415],"thead",{},[416,417,418,422],"tr",{},[419,420,421],"th",{},"Property",[419,423,424],{},"Value",[426,427,428,440,451],"tbody",{},[416,429,430,435],{},[431,432,433],"td",{},[75,434,75],{},[431,436,437],{},[75,438,439],{},"\"ERR_BODY_TOO_LARGE\"",[416,441,442,447],{},[431,443,444],{},[75,445,446],{},"statusCode",[431,448,449],{},[75,450,205],{},[416,452,453,458],{},[431,454,455],{},[75,456,457],{},"status",[431,459,460],{},[75,461,205],{},[119,463,465],{"className":121,"code":464,"language":123,"meta":124,"style":124},"import { createBodyTooLargeError, limitRequestBody } from \"srvx/body-limit\";\n\nconst safeRequest = limitRequestBody(request, 1024 * 1024);\ntry {\n  return Response.json(await safeRequest.json());\n} catch (error) {\n  if (error.code === \"ERR_BODY_TOO_LARGE\") {\n    return new Response(\"Payload Too Large\", { status: error.statusCode });\n  }\n  throw error;\n}\n\n// Or construct the error directly to enforce a limit elsewhere:\nthrow createBodyTooLargeError(1024 * 1024);\n",[75,466,467,480,484,504,512,535,547,565,585,591,600,606,611,617],{"__ignoreMap":124},[128,468,469,471,474,476,478],{"class":130,"line":131},[128,470,135],{"class":134},[128,472,473],{"class":138}," { createBodyTooLargeError, limitRequestBody } ",[128,475,142],{"class":134},[128,477,146],{"class":145},[128,479,149],{"class":138},[128,481,482],{"class":130,"line":152},[128,483,156],{"emptyLinePlaceholder":155},[128,485,486,488,490,492,494,496,498,500,502],{"class":130,"line":159},[128,487,162],{"class":134},[128,489,306],{"class":165},[128,491,169],{"class":134},[128,493,311],{"class":172},[128,495,314],{"class":138},[128,497,179],{"class":165},[128,499,182],{"class":134},[128,501,185],{"class":165},[128,503,192],{"class":138},[128,505,506,509],{"class":130,"line":327},[128,507,508],{"class":134},"try",[128,510,511],{"class":138}," {\n",[128,513,514,517,520,522,525,528,530,532],{"class":130,"line":333},[128,515,516],{"class":134},"  return",[128,518,519],{"class":138}," Response.",[128,521,230],{"class":172},[128,523,524],{"class":138},"(",[128,526,527],{"class":134},"await",[128,529,346],{"class":138},[128,531,230],{"class":172},[128,533,534],{"class":138},"());\n",[128,536,538,541,544],{"class":130,"line":537},6,[128,539,540],{"class":138},"} ",[128,542,543],{"class":134},"catch",[128,545,546],{"class":138}," (error) {\n",[128,548,550,553,556,559,562],{"class":130,"line":549},7,[128,551,552],{"class":134},"  if",[128,554,555],{"class":138}," (error.code ",[128,557,558],{"class":134},"===",[128,560,561],{"class":145}," \"ERR_BODY_TOO_LARGE\"",[128,563,564],{"class":138},") {\n",[128,566,568,571,574,577,579,582],{"class":130,"line":567},8,[128,569,570],{"class":134},"    return",[128,572,573],{"class":134}," new",[128,575,576],{"class":172}," Response",[128,578,524],{"class":138},[128,580,581],{"class":145},"\"Payload Too Large\"",[128,583,584],{"class":138},", { status: error.statusCode });\n",[128,586,588],{"class":130,"line":587},9,[128,589,590],{"class":138},"  }\n",[128,592,594,597],{"class":130,"line":593},10,[128,595,596],{"class":134},"  throw",[128,598,599],{"class":138}," error;\n",[128,601,603],{"class":130,"line":602},11,[128,604,605],{"class":138},"}\n",[128,607,609],{"class":130,"line":608},12,[128,610,156],{"emptyLinePlaceholder":155},[128,612,614],{"class":130,"line":613},13,[128,615,616],{"class":188},"// Or construct the error directly to enforce a limit elsewhere:\n",[128,618,620,623,626,628,630,632,634],{"class":130,"line":619},14,[128,621,622],{"class":134},"throw",[128,624,625],{"class":172}," createBodyTooLargeError",[128,627,524],{"class":138},[128,629,179],{"class":165},[128,631,182],{"class":134},[128,633,185],{"class":165},[128,635,192],{"class":138},[105,637,639],{"id":638},"custom-error","Custom error",[67,641,642,643,646,647,649,650,652,653,656,657,660],{},"Both helpers accept an options object whose ",[75,644,645],{},"createError"," overrides the error thrown on overflow — used for the streaming limit, the ",[75,648,357],{}," fast path, and (for ",[75,651,213],{},") any ",[75,654,655],{},"clone()",". This lets a framework map an overflow straight to its own error/response type instead of string-matching ",[75,658,659],{},"ERR_BODY_TOO_LARGE",":",[119,662,664],{"className":121,"code":663,"language":123,"meta":124,"style":124},"import { limitRequestBody } from \"srvx/body-limit\";\n\nconst safeRequest = limitRequestBody(request, 1024 * 1024, {\n  createError: (max) => new MyHttpError(413, `Body exceeds ${max} bytes`),\n});\n// a raw `safeRequest.text()` overflow now throws `MyHttpError` directly\n",[75,665,666,678,682,703,743,748],{"__ignoreMap":124},[128,667,668,670,672,674,676],{"class":130,"line":131},[128,669,135],{"class":134},[128,671,289],{"class":138},[128,673,142],{"class":134},[128,675,146],{"class":145},[128,677,149],{"class":138},[128,679,680],{"class":130,"line":152},[128,681,156],{"emptyLinePlaceholder":155},[128,683,684,686,688,690,692,694,696,698,700],{"class":130,"line":159},[128,685,162],{"class":134},[128,687,306],{"class":165},[128,689,169],{"class":134},[128,691,311],{"class":172},[128,693,314],{"class":138},[128,695,179],{"class":165},[128,697,182],{"class":134},[128,699,185],{"class":165},[128,701,702],{"class":138},", {\n",[128,704,705,708,711,715,718,721,723,726,728,730,732,735,737,740],{"class":130,"line":327},[128,706,707],{"class":172},"  createError",[128,709,710],{"class":138},": (",[128,712,714],{"class":713},"sQHwn","max",[128,716,717],{"class":138},") ",[128,719,720],{"class":134},"=>",[128,722,573],{"class":134},[128,724,725],{"class":172}," MyHttpError",[128,727,524],{"class":138},[128,729,205],{"class":165},[128,731,267],{"class":138},[128,733,734],{"class":145},"`Body exceeds ${",[128,736,714],{"class":138},[128,738,739],{"class":145},"} bytes`",[128,741,742],{"class":138},"),\n",[128,744,745],{"class":130,"line":333},[128,746,747],{"class":138},"});\n",[128,749,750],{"class":130,"line":537},[128,751,752],{"class":188},"// a raw `safeRequest.text()` overflow now throws `MyHttpError` directly\n",[67,754,755,756,758,759,763],{},"The factory receives the limit (bytes) and returns the value to throw. Omitting ",[75,757,645],{}," keeps the default ",[71,760,761,206],{"href":202},[75,762,205],{},".",[765,766,767],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}",{"title":124,"searchDepth":152,"depth":152,"links":769},[770,771,772,773],{"id":107,"depth":152,"text":110},{"id":210,"depth":152,"text":213},{"id":392,"depth":152,"text":393},{"id":638,"depth":152,"text":639},"Reusable, runtime-agnostic helpers for enforcing request body size limits.","md",{"icon":55},{"icon":55},{"title":52,"description":774},"Dd9LJ20taqUWxxsQfGZ5jUNlD_Zuah4vylv79zqQIls",[781,783],{"title":47,"path":48,"stem":49,"description":782,"icon":50,"children":-1},"Use the srvx CLI command to easily start a development or production server.",{"title":57,"path":58,"stem":59,"description":784,"icon":60,"children":-1},"AWS Lambda compatibility",1784739506026]