{"id":4924,"date":"2026-02-18T05:43:08","date_gmt":"2026-02-18T05:43:08","guid":{"rendered":"https:\/\/softcolontechnologies.com\/blogs\/?p=4924"},"modified":"2026-02-18T05:44:05","modified_gmt":"2026-02-18T05:44:05","slug":"limiting-request-body-file-upload-size-in-caddy","status":"publish","type":"post","link":"https:\/\/www.softcolon.com\/blogs\/limiting-request-body-file-upload-size-in-caddy\/","title":{"rendered":"Limiting Request Body \/ File Upload Size in Caddy"},"content":{"rendered":"<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Introduction: Why Request Size Limits Matter<\/h2>\n<p class=\" text-lg my-6\">Imagine you run a file upload service or API. One day, someone uploads a 50 GB file to your server. Your disk fills up instantly. Your server crashes. All your users can&#8217;t access the service.<\/p>\n<p class=\" text-lg my-6\">Or worse: A bot makes 1,000 requests, each with a 1 MB payload, consuming all your memory. Your application becomes unresponsive.<\/p>\n<p class=\" text-lg my-6\"><strong>Request body size limiting<\/strong> is a critical security feature that protects your server from:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Disk exhaustion:<\/strong> Large files filling up your storage<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Memory exhaustion:<\/strong> Large payloads consuming all RAM<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Bandwidth waste:<\/strong> Unnecessary data transfer<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>DoS attacks:<\/strong> Attackers deliberately sending huge requests<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Cost:<\/strong> Expensive bandwidth and storage bills<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Performance:<\/strong> Server slowdowns from processing large files<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\">Without limits, any client can send unlimited data, and your server must accept it all before processing.<\/p>\n<p class=\" text-lg my-6\">With limits, you control:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Maximum file upload size<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Maximum API request size<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Maximum body size for form submissions<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Different limits for different endpoints<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\">Caddy makes implementing these limits trivial through the <code class=\"break-words rounded bg-[#24292E] px-2 py-1 text-[#EEEEEE]\">request_body<\/code> directive.<\/p>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Understanding Request Bodies<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">What is a Request Body?<\/h3>\n<p class=\" text-lg my-6\">When a client (browser, API client, etc.) sends data to your server, it comes in an HTTP request. The request has:<\/p>\n<ol class=\"list-decimal ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Headers:<\/strong> Metadata about the request (Content-Type, Authorization, etc.)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Body:<\/strong> The actual data being sent<\/p>\n<\/li>\n<\/ol>\n<p class=\" text-lg my-6\"><strong>Examples of request bodies:<\/strong><\/p>\n<table>\n<thead>\n<tr>\n<th>Type<\/th>\n<th>Example<\/th>\n<th>Typical Size<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>JSON API request<\/td>\n<td><code class=\"break-words rounded bg-[#24292E] px-2 py-1 text-[#EEEEEE]\">{\"name\":\"John\",\"age\":30}<\/code><\/td>\n<td>1-10 KB<\/td>\n<\/tr>\n<tr>\n<td>Form submission<\/td>\n<td><code class=\"break-words rounded bg-[#24292E] px-2 py-1 text-[#EEEEEE]\">email=john@example.com&amp;password=...<\/code><\/td>\n<td>1-100 KB<\/td>\n<\/tr>\n<tr>\n<td>Small file upload<\/td>\n<td>Photo from phone<\/td>\n<td>1-5 MB<\/td>\n<\/tr>\n<tr>\n<td>Large file upload<\/td>\n<td>Video file<\/td>\n<td>100 MB &#8211; 1 GB<\/td>\n<\/tr>\n<tr>\n<td>Malicious request<\/td>\n<td>Attacker sending garbage data<\/td>\n<td>1-100 GB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Where the Request Body is Processed<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Client<\/span> sends request <span class=\"hljs-keyword\">with<\/span> body\n    \u2193\n<span class=\"hljs-title class_\">Caddy<\/span> receives the request\n    \u2193\n<span class=\"hljs-title class_\">Caddy<\/span> <span class=\"hljs-attr\">checks<\/span>: <span class=\"hljs-title class_\">Is<\/span> the body size within the limit?\n    \u2193\n<span class=\"hljs-variable constant_\">YES<\/span> \u2192 <span class=\"hljs-title class_\">Caddy<\/span> accepts body, forwards to your app\n<span class=\"hljs-variable constant_\">NO<\/span> \u2192 <span class=\"hljs-title class_\">Caddy<\/span> rejects <span class=\"hljs-title function_\">request<\/span> (<span class=\"hljs-number\">413<\/span> <span class=\"hljs-title class_\">Payload<\/span> <span class=\"hljs-title class_\">Too<\/span> <span class=\"hljs-title class_\">Large<\/span>)\n    \u2193\n<span class=\"hljs-title class_\">Your<\/span> <span class=\"hljs-title class_\">Node<\/span>.<span class=\"hljs-property\">js<\/span> app processes the <span class=\"hljs-title function_\">request<\/span> (<span class=\"hljs-keyword\">if<\/span> accepted)\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Key point:<\/strong> Size checking happens at Caddy level, before it reaches your application. This protects your app from even receiving oversized requests.<\/p>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Default Behavior (No Limits)<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">What Happens Without Limits<\/h3>\n<p class=\" text-lg my-6\">By default, Caddy has no built-in request body size limit. It will accept requests of any size (limited only by available disk space and RAM).<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># <span class=\"hljs-title class_\">Default<\/span> - no limits\nexample.<span class=\"hljs-property\">com<\/span> {\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Problems:<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Attacker<\/span> uploads <span class=\"hljs-number\">100<\/span> <span class=\"hljs-variable constant_\">GB<\/span> file\n    \u2193\n<span class=\"hljs-title class_\">Caddy<\/span> accepts all <span class=\"hljs-number\">100<\/span> <span class=\"hljs-variable constant_\">GB<\/span> into memory\n    \u2193\n<span class=\"hljs-title class_\">Server<\/span> runs out <span class=\"hljs-keyword\">of<\/span> <span class=\"hljs-variable constant_\">RAM<\/span>\n    \u2193\n<span class=\"hljs-title class_\">Server<\/span> crashes\n    \u2193\n<span class=\"hljs-title class_\">All<\/span> legitimate users get <span class=\"hljs-string\">\"Service Unavailable\"<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Why You Need Limits<\/h3>\n<p class=\" text-lg my-6\">Real-world attacks:<\/p>\n<p class=\" text-lg my-6\"><strong>Attack 1: Disk Exhaustion<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Attacker<\/span> runs <span class=\"hljs-attr\">script<\/span>:\n<span class=\"hljs-keyword\">for<\/span> i <span class=\"hljs-keyword\">in<\/span> {<span class=\"hljs-number\">1.<\/span><span class=\"hljs-number\">.100<\/span>}; <span class=\"hljs-keyword\">do<\/span>\n    curl -X <span class=\"hljs-variable constant_\">POST<\/span> --data @1gb-file.<span class=\"hljs-property\">bin<\/span> <span class=\"hljs-attr\">https<\/span>:<span class=\"hljs-comment\">\/\/example.com\/upload<\/span>\ndone\n\n<span class=\"hljs-title class_\">Result<\/span>:\n- <span class=\"hljs-number\">100<\/span> <span class=\"hljs-variable constant_\">GB<\/span> written to disk\n- <span class=\"hljs-title class_\">Disk<\/span> is full\n- <span class=\"hljs-title class_\">Application<\/span> can<span class=\"hljs-string\">'t write logs or database records\n- Service becomes unavailable\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Attack 2: Memory Exhaustion<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Attacker<\/span> <span class=\"hljs-attr\">sends<\/span>:\n<span class=\"hljs-variable constant_\">POST<\/span> \/api\/submit\n<span class=\"hljs-title class_\">Content<\/span>-<span class=\"hljs-title class_\">Length<\/span>: 100GB\n[<span class=\"hljs-number\">100<\/span> <span class=\"hljs-variable constant_\">GB<\/span> <span class=\"hljs-keyword\">of<\/span> data]\n\n<span class=\"hljs-title class_\">Caddy<\/span> starts receiving the request\n<span class=\"hljs-title class_\">Memory<\/span> fills <span class=\"hljs-attr\">up<\/span>: <span class=\"hljs-number\">25<\/span>%, <span class=\"hljs-number\">50<\/span>%, <span class=\"hljs-number\">75<\/span>%, <span class=\"hljs-number\">100<\/span>%\n<span class=\"hljs-title class_\">Server<\/span> becomes sluggish\n<span class=\"hljs-title class_\">Application<\/span> timeout\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Attack 3: Bandwidth Waste<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Attacker<\/span> or legitimate user misconfigures <span class=\"hljs-attr\">client<\/span>:\n<span class=\"hljs-title class_\">Client<\/span> uploads entire hard <span class=\"hljs-title function_\">drive<\/span> (<span class=\"hljs-number\">500<\/span> <span class=\"hljs-variable constant_\">GB<\/span>)\n<span class=\"hljs-title class_\">Your<\/span> bandwidth <span class=\"hljs-attr\">bill<\/span>: $5,<span class=\"hljs-number\">000<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Attack 4: Slow Clients<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">Attacker<\/span> sends data very <span class=\"hljs-title function_\">slowly<\/span> (<span class=\"hljs-number\">1<\/span> byte per second)\n<span class=\"hljs-title class_\">Caddy<\/span> has to keep connection open\n<span class=\"hljs-title class_\">After<\/span> <span class=\"hljs-number\">100<\/span>,<span class=\"hljs-number\">000<\/span> slow connections\n<span class=\"hljs-title class_\">All<\/span> connection slots are full\n<span class=\"hljs-title class_\">Legitimate<\/span> users can<span class=\"hljs-string\">'t connect\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Setting Limits<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Understanding Size Units<\/h3>\n<p class=\" text-lg my-6\">Caddy accepts various size units:<\/p>\n<table>\n<thead>\n<tr>\n<th>Unit<\/th>\n<th>Meaning<\/th>\n<th>Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>B<\/td>\n<td>Bytes<\/td>\n<td>1024B = 1 KB<\/td>\n<\/tr>\n<tr>\n<td>KB<\/td>\n<td>Kilobytes<\/td>\n<td>1KB = 1,000 bytes<\/td>\n<\/tr>\n<tr>\n<td>MB<\/td>\n<td>Megabytes<\/td>\n<td>1MB = 1,000 KB<\/td>\n<\/tr>\n<tr>\n<td>GB<\/td>\n<td>Gigabytes<\/td>\n<td>1GB = 1,000 MB<\/td>\n<\/tr>\n<tr>\n<td>KiB<\/td>\n<td>Kibibytes (binary)<\/td>\n<td>1KiB = 1,024 bytes<\/td>\n<\/tr>\n<tr>\n<td>MiB<\/td>\n<td>Mebibytes (binary)<\/td>\n<td>1MiB = 1,024 KB<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\" text-lg my-6\"><strong>Note:<\/strong> Most people use MB (decimal), but MiB (binary) is technically more accurate for computers.<\/p>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Quick Reference: Common Limits<\/h3>\n<table>\n<thead>\n<tr>\n<th>Use Case<\/th>\n<th>Recommended Limit<\/th>\n<th>Reasoning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>JSON API request<\/td>\n<td>1 MB<\/td>\n<td>Plenty for structured data<\/td>\n<\/tr>\n<tr>\n<td>Form submission<\/td>\n<td>5 MB<\/td>\n<td>Covers most normal forms<\/td>\n<\/tr>\n<tr>\n<td>Small file upload<\/td>\n<td>10 MB<\/td>\n<td>Photos, documents<\/td>\n<\/tr>\n<tr>\n<td>Medium file upload<\/td>\n<td>100 MB<\/td>\n<td>Videos, large files<\/td>\n<\/tr>\n<tr>\n<td>Large file upload<\/td>\n<td>1 GB<\/td>\n<td>Professional media<\/td>\n<\/tr>\n<tr>\n<td>Very large (streaming)<\/td>\n<td>5 GB<\/td>\n<td>Use chunked upload instead<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Pattern 1: Global Request Body Limit<\/h2>\n<p class=\" text-lg my-6\">Apply the same limit to your entire domain.<\/p>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Protect Against Large File Uploads<\/h3>\n<p class=\" text-lg my-6\">Limit entire domain to 10 MB:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 10MB\n    }\n\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>What this does:<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">5<\/span> <span class=\"hljs-variable constant_\">MB<\/span> file \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span>\n<span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">15<\/span> <span class=\"hljs-variable constant_\">MB<\/span> file \u2192 \u274c <span class=\"hljs-title class_\">Rejected<\/span> (<span class=\"hljs-variable constant_\">HTTP<\/span> <span class=\"hljs-number\">413<\/span>)\n<span class=\"hljs-variable constant_\">API<\/span> request <span class=\"hljs-keyword\">with<\/span> <span class=\"hljs-number\">2<\/span> <span class=\"hljs-variable constant_\">MB<\/span> <span class=\"hljs-title class_\">JSON<\/span> \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span>\n<span class=\"hljs-title class_\">Form<\/span> submission <span class=\"hljs-keyword\">with<\/span> <span class=\"hljs-number\">500<\/span> <span class=\"hljs-variable constant_\">KB<\/span> \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>HTTP Response When Exceeded:<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-variable constant_\">HTTP<\/span>\/<span class=\"hljs-number\">1.1<\/span> <span class=\"hljs-number\">413<\/span> <span class=\"hljs-title class_\">Payload<\/span> <span class=\"hljs-title class_\">Too<\/span> <span class=\"hljs-title class_\">Large<\/span>\n<span class=\"hljs-title class_\">Content<\/span>-<span class=\"hljs-title class_\">Type<\/span>: text\/plain\n\n<span class=\"hljs-title class_\">Payload<\/span> <span class=\"hljs-title class_\">Too<\/span> <span class=\"hljs-title class_\">Large<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Conservative Limit (API Only)<\/h3>\n<p class=\" text-lg my-6\">For REST APIs without file uploads, use a strict limit:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">api.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 1MB\n    }\n\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3001<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Protects against:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Accidental large submissions<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">JSON bomb attacks (deeply nested JSON)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Bulk operation abuse<\/p>\n<\/li>\n<\/ul>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Generous Limit (File Server)<\/h3>\n<p class=\" text-lg my-6\">For applications that accept file uploads:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">upload.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 1GB\n    }\n\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3002<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Allows large file uploads while still preventing excessively large ones.<\/p>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Multiple Domains with Different Limits<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># <span class=\"hljs-title class_\">Strict<\/span> <span class=\"hljs-variable constant_\">API<\/span> - no file uploads\napi.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 1MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3001<\/span>\n}\n\n# <span class=\"hljs-title class_\">File<\/span> service - large uploads\nfiles.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 100MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3002<\/span>\n}\n\n# <span class=\"hljs-title class_\">Public<\/span> website - moderate limit\nwww.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 10MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Pattern 2: Route-Specific Request Body Limits<\/h2>\n<p class=\" text-lg my-6\">Only apply limits to certain routes. Different endpoints have different needs.<\/p>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Protect Upload Endpoint Only<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    handle_path \/upload<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 5MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Access behavior:<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-variable constant_\">POST<\/span> \/upload\/file \u2192 <span class=\"hljs-title class_\">Limited<\/span> to <span class=\"hljs-number\">5<\/span> <span class=\"hljs-variable constant_\">MB<\/span>\n<span class=\"hljs-variable constant_\">GET<\/span> \/products \u2192 <span class=\"hljs-title class_\">No<\/span> <span class=\"hljs-title function_\">limit<\/span> (just gets data)\n<span class=\"hljs-variable constant_\">POST<\/span> \/api\/search \u2192 <span class=\"hljs-title class_\">No<\/span> <span class=\"hljs-title function_\">limit<\/span> (small <span class=\"hljs-title class_\">JSON<\/span>)\n<span class=\"hljs-variable constant_\">POST<\/span> \/contact \u2192 <span class=\"hljs-title class_\">No<\/span> <span class=\"hljs-title function_\">limit<\/span> (form is small)\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Different Limits for Different Upload Types<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Profile<\/span> pictures - small files\n    handle_path \/upload\/profile-pic<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 5MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Document uploads - moderate size\n    handle_path \/upload\/documents\/* {\n        request_body {\n            max_size 50MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Video uploads - larger size\n    handle_path \/upload\/videos\/* {\n        request_body {\n            max_size 500MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Everything else - no upload limit\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Usage:<\/strong><\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">3<\/span> <span class=\"hljs-variable constant_\">MB<\/span> photo \u2192 \/upload\/profile-pic \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span> (under <span class=\"hljs-number\">5<\/span> <span class=\"hljs-variable constant_\">MB<\/span>)\n<span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">10<\/span> <span class=\"hljs-variable constant_\">MB<\/span> <span class=\"hljs-variable language_\">document<\/span> \u2192 \/upload\/documents \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span> (under <span class=\"hljs-number\">50<\/span> <span class=\"hljs-variable constant_\">MB<\/span>)\n<span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">200<\/span> <span class=\"hljs-variable constant_\">MB<\/span> video \u2192 \/upload\/videos \u2192 \u2705 <span class=\"hljs-title class_\">Allowed<\/span> (under <span class=\"hljs-number\">500<\/span> <span class=\"hljs-variable constant_\">MB<\/span>)\n<span class=\"hljs-title class_\">User<\/span> uploads <span class=\"hljs-number\">10<\/span> <span class=\"hljs-variable constant_\">MB<\/span> to \/upload\/profile-pic \u2192 \u274c <span class=\"hljs-title class_\">Rejected<\/span> (exceeds <span class=\"hljs-number\">5<\/span> <span class=\"hljs-variable constant_\">MB<\/span>)\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Protect APIs by Endpoint<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">api.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Bulk<\/span> <span class=\"hljs-keyword\">import<\/span> - large payloads\n    handle_path \/api\/v1\/<span class=\"hljs-keyword\">import<\/span><span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 100MB\n        }\n        reverse_proxy localhost:3001\n    }\n\n    # Standard API - moderate payloads\n    handle_path \/api\/v1\/* {\n        request_body {\n            max_size 10MB\n        }\n        reverse_proxy localhost:3001\n    }\n\n    # Public endpoints - small payloads\n    handle_path \/api\/public\/* {\n        request_body {\n            max_size 1MB\n        }\n        reverse_proxy localhost:3001\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Combine with Other Security<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">File<\/span> upload <span class=\"hljs-keyword\">with<\/span> multiple protections\n    handle_path \/upload<span class=\"hljs-comment\">\/* {\n        # Limit request size\n        request_body {\n            max_size 50MB\n        }\n\n        # Rate limit uploads\n        rate_limit {\n            zone uploads {\n                key {remote_host}\n                events 10\n                window 1h\n            }\n        }\n\n        # Require authentication\n        basicauth {\n            user $2a$12$abc123...\n        }\n\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Real-World Scenarios<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Scenario 1: E-Commerce Platform<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">shop.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Product<\/span> images - moderate limit\n    handle_path \/upload\/products<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 10MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # User profile pictures - small limit\n    handle_path \/upload\/profile\/* {\n        request_body {\n            max_size 5MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # API for mobile app - strict limit\n    handle_path \/api\/* {\n        request_body {\n            max_size 5MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Checkout form - small limit\n    handle_path \/checkout {\n        request_body {\n            max_size 1MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Everything else\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Scenario 2: Document Management System<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">docs.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Document<\/span> uploads - large files allowed\n    handle_path \/api\/documents\/upload {\n        request_body {\n            max_size 500MB\n        }\n\n        # <span class=\"hljs-title class_\">Require<\/span> authentication\n        basicauth {\n            user $2a$12$abc123...\n        }\n\n        # <span class=\"hljs-title class_\">Rate<\/span> limit to prevent abuse\n        rate_limit {\n            zone uploads {\n                key {http.<span class=\"hljs-property\">request<\/span>.<span class=\"hljs-property\">header<\/span>.<span class=\"hljs-property\">Authorization<\/span>}\n                events <span class=\"hljs-number\">20<\/span>\n                <span class=\"hljs-variable language_\">window<\/span> 1h\n            }\n        }\n\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3001<\/span>\n    }\n\n    # <span class=\"hljs-variable constant_\">API<\/span> queries - small payloads\n    handle_path \/api<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 5MB\n        }\n        reverse_proxy localhost:3001\n    }\n\n    handle {\n        reverse_proxy localhost:3001\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Scenario 3: SaaS with Tiered Plans<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">app.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Free<\/span> tier - strict limits\n    handle_path \/api\/free<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 1MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Professional tier - moderate limits\n    handle_path \/api\/pro\/* {\n        request_body {\n            max_size 50MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # Enterprise tier - generous limits\n    handle_path \/api\/enterprise\/* {\n        request_body {\n            max_size 1GB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    # File upload - depends on plan\n    handle_path \/upload\/* {\n        @pro_user {\n            header X-Plan professional\n        }\n\n        @enterprise_user {\n            header X-Plan enterprise\n        }\n\n        handle @enterprise_user {\n            request_body {\n                max_size 1GB\n            }\n            reverse_proxy localhost:3000\n        }\n\n        handle @pro_user {\n            request_body {\n                max_size 100MB\n            }\n            reverse_proxy localhost:3000\n        }\n\n        # Free tier\n        request_body {\n            max_size 10MB\n        }\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Common Mistakes to Avoid<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 1: Setting Limits Too Small<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">Too<\/span> restrictive\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 1KB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Problems:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Users can&#8217;t submit normal forms (which are usually &gt; 1 KB)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">APIs reject legitimate requests<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Lots of frustrated users<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Set reasonable limits based on your use case:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span>\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 10MB  # <span class=\"hljs-title class_\">Reasonable<\/span> <span class=\"hljs-keyword\">default<\/span>\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 2: Setting Limits Too Large<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">No<\/span> real protection\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 100GB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Problems:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Doesn&#8217;t protect against large file attacks<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Disk can still fill up<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Memory can still be exhausted<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Set realistic limits:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span> - <span class=\"hljs-title class_\">Based<\/span> on actual use <span class=\"hljs-keyword\">case<\/span>\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 50MB  # <span class=\"hljs-title class_\">If<\/span> handling uploads\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 3: Forgetting to Limit Upload Endpoints<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">Upload<\/span> endpoint has no limit\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 10MB\n    }\n\n    handle_path \/upload<span class=\"hljs-comment\">\/* {\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">The global limit applies, but it might be too strict for uploads or too generous.<\/p>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Explicitly set limits for each endpoint:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span>\nexample.<span class=\"hljs-property\">com<\/span> {\n    handle_path \/upload<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 500MB  # Specific for uploads\n        }\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        request_body {\n            max_size 10MB   # Default for others\n        }\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 4: No Limits on Internal APIs<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">Internal<\/span> <span class=\"hljs-variable constant_\">API<\/span> unprotected\ninternal.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Even internal APIs can be attacked by:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Compromised internal services<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Bugs in other services making oversized requests<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Intentional abuse by disgruntled employees<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Protect internal endpoints too:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span>\ninternal.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 50MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 5: Not Testing Actual File Sizes<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">Set<\/span> a limit without testing\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 5MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">You set 5 MB, but users need to upload 8 MB files. They get rejected. Bad UX.<\/p>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Test with actual use cases:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-bash whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-comment\"># Test uploading a file<\/span>\ncurl -F <span class=\"hljs-string\">\"file=@large-file.bin\"<\/span> https:\/\/example.com\/upload\n\n<span class=\"hljs-comment\"># Test with exactly the size limit<\/span>\n<span class=\"hljs-built_in\">dd<\/span> <span class=\"hljs-keyword\">if<\/span>=\/dev\/zero bs=1M count=5 of=test-file.bin\ncurl -F <span class=\"hljs-string\">\"file=@test-file.bin\"<\/span> https:\/\/example.com\/upload\n\n<span class=\"hljs-comment\"># Test exceeding the limit<\/span>\n<span class=\"hljs-built_in\">dd<\/span> <span class=\"hljs-keyword\">if<\/span>=\/dev\/zero bs=1M count=6 of=test-file-large.bin\ncurl -F <span class=\"hljs-string\">\"file=@test-file-large.bin\"<\/span> https:\/\/example.com\/upload\n<span class=\"hljs-comment\"># Should get 413 Payload Too Large<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 6: Limiting GET Requests<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">WRONG<\/span> - <span class=\"hljs-title class_\">Limits<\/span> <span class=\"hljs-variable constant_\">GET<\/span> which has no body\nexample.<span class=\"hljs-property\">com<\/span> {\n    handle_path \/api\/search {\n        request_body {\n            max_size 1MB\n        }\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">GET requests (fetching data) don&#8217;t have bodies, so this limit does nothing. But it&#8217;s confusing.<\/p>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Only set limits on routes that receive bodies (POST, PUT, PATCH):<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span> - <span class=\"hljs-title class_\">Only<\/span> on endpoints <span class=\"hljs-keyword\">with<\/span> bodies\nexample.<span class=\"hljs-property\">com<\/span> {\n    handle_path \/api\/search {\n        # <span class=\"hljs-title class_\">No<\/span> limit needed, <span class=\"hljs-variable constant_\">GET<\/span> has no body\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n\n    handle_path \/api\/create {\n        # <span class=\"hljs-title class_\">Limit<\/span> <span class=\"hljs-variable constant_\">POST<\/span> requests\n        request_body {\n            max_size 10MB\n        }\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Mistake 7: Not Considering Concurrent Uploads<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u274c <span class=\"hljs-variable constant_\">INCOMPLETE<\/span> - <span class=\"hljs-title class_\">Limit<\/span> per request, but not total\nexample.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 500MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">Problems:<\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Each user can upload 500 MB<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">If 100 users upload simultaneously, that&#8217;s 50 GB total<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Still fills disk<\/p>\n<\/li>\n<\/ul>\n<p class=\" text-lg my-6\"><strong>Solution:<\/strong> Combine with rate limiting:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># \u2705 <span class=\"hljs-variable constant_\">CORRECT<\/span> - <span class=\"hljs-title class_\">Limit<\/span> individual uploads <span class=\"hljs-variable constant_\">AND<\/span> frequency\nexample.<span class=\"hljs-property\">com<\/span> {\n    rate_limit {\n        zone uploads {\n            key {remote_host}\n            events <span class=\"hljs-number\">5<\/span>          # <span class=\"hljs-title class_\">Max<\/span> <span class=\"hljs-number\">5<\/span> uploads per hour\n            <span class=\"hljs-variable language_\">window<\/span> 1h\n        }\n    }\n\n    handle_path \/upload<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 500MB    # Per upload\n        }\n        reverse_proxy localhost:3000\n    }\n\n    handle {\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Monitoring and Debugging<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Logging Oversized Requests<\/h3>\n<p class=\" text-lg my-6\">Enable Caddy logging to track rejected requests:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    log {\n        output stdout\n        format json\n    }\n\n    request_body {\n        max_size 10MB\n    }\n\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\">View logs:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-bash whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-comment\"># Watch for 413 errors<\/span>\n<span class=\"hljs-built_in\">sudo<\/span> journalctl -u caddy -f | grep <span class=\"hljs-string\">\"413\"<\/span>\n\n<span class=\"hljs-comment\"># Or in JSON<\/span>\ndocker logs caddy-container | jq <span class=\"hljs-string\">'select(.status==413)'<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Check Request Size Before Upload<\/h3>\n<p class=\" text-lg my-6\">In your application, warn users about size limits:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-javascript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-comment\">\/\/ Check file size before upload<\/span>\n<span class=\"hljs-variable language_\">document<\/span>.<span class=\"hljs-title function_\">getElementById<\/span>(<span class=\"hljs-string\">'file-input'<\/span>).<span class=\"hljs-title function_\">addEventListener<\/span>(<span class=\"hljs-string\">'change'<\/span>, <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>) =&gt;<\/span> {\n    <span class=\"hljs-keyword\">const<\/span> file = e.<span class=\"hljs-property\">target<\/span>.<span class=\"hljs-property\">files<\/span>[<span class=\"hljs-number\">0<\/span>];\n    <span class=\"hljs-keyword\">const<\/span> maxSize = <span class=\"hljs-number\">10<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span>; <span class=\"hljs-comment\">\/\/ 10 MB<\/span>\n    \n    <span class=\"hljs-keyword\">if<\/span> (file.<span class=\"hljs-property\">size<\/span> &gt; maxSize) {\n        <span class=\"hljs-title function_\">alert<\/span>(<span class=\"hljs-string\">`File too large. Max size: 10 MB, Your file: <span class=\"hljs-subst\">${(file.size \/ <span class=\"hljs-number\">1024<\/span> \/ <span class=\"hljs-number\">1024<\/span>).toFixed(<span class=\"hljs-number\">2<\/span>)}<\/span> MB`<\/span>);\n        e.<span class=\"hljs-property\">target<\/span>.<span class=\"hljs-property\">value<\/span> = <span class=\"hljs-string\">''<\/span>;\n    }\n});\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Test Different File Sizes<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-bash whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-comment\"># Test with 1 MB file<\/span>\n<span class=\"hljs-built_in\">dd<\/span> <span class=\"hljs-keyword\">if<\/span>=\/dev\/urandom bs=1M count=1 of=file-1mb.bin\ncurl -X POST -F <span class=\"hljs-string\">\"file=@file-1mb.bin\"<\/span> https:\/\/example.com\/upload\n\n<span class=\"hljs-comment\"># Test with 10 MB file<\/span>\n<span class=\"hljs-built_in\">dd<\/span> <span class=\"hljs-keyword\">if<\/span>=\/dev\/urandom bs=1M count=10 of=file-10mb.bin\ncurl -X POST -F <span class=\"hljs-string\">\"file=@file-10mb.bin\"<\/span> https:\/\/example.com\/upload\n\n<span class=\"hljs-comment\"># Test with 20 MB file (should fail if limit is 10 MB)<\/span>\n<span class=\"hljs-built_in\">dd<\/span> <span class=\"hljs-keyword\">if<\/span>=\/dev\/urandom bs=1M count=20 of=file-20mb.bin\ncurl -X POST -F <span class=\"hljs-string\">\"file=@file-20mb.bin\"<\/span> https:\/\/example.com\/upload\n<span class=\"hljs-comment\"># Should get: 413 Payload Too Large<\/span>\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Handling Large Uploads Properly<\/h2>\n<p class=\" text-lg my-6\">When users need to upload files larger than reasonable request limits, use <strong>chunked uploads<\/strong>:<\/p>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Client-Side Chunked Upload<\/h3>\n<p class=\" text-lg my-6\">Instead of uploading one large file, break it into smaller chunks:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-javascript whitespace-pre-wrap break-words text-gray-300\"><span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title function_\">uploadLargeFile<\/span>(<span class=\"hljs-params\">file, chunkSize = <span class=\"hljs-number\">5<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span><\/span>) {\n    <span class=\"hljs-keyword\">const<\/span> chunks = <span class=\"hljs-title class_\">Math<\/span>.<span class=\"hljs-title function_\">ceil<\/span>(file.<span class=\"hljs-property\">size<\/span> \/ chunkSize);\n    \n    <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">let<\/span> i = <span class=\"hljs-number\">0<\/span>; i &lt; chunks; i++) {\n        <span class=\"hljs-keyword\">const<\/span> start = i * chunkSize;\n        <span class=\"hljs-keyword\">const<\/span> end = <span class=\"hljs-title class_\">Math<\/span>.<span class=\"hljs-title function_\">min<\/span>(start + chunkSize, file.<span class=\"hljs-property\">size<\/span>);\n        <span class=\"hljs-keyword\">const<\/span> chunk = file.<span class=\"hljs-title function_\">slice<\/span>(start, end);\n        \n        <span class=\"hljs-keyword\">const<\/span> formData = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">FormData<\/span>();\n        formData.<span class=\"hljs-title function_\">append<\/span>(<span class=\"hljs-string\">'chunk'<\/span>, chunk);\n        formData.<span class=\"hljs-title function_\">append<\/span>(<span class=\"hljs-string\">'chunkIndex'<\/span>, i);\n        formData.<span class=\"hljs-title function_\">append<\/span>(<span class=\"hljs-string\">'totalChunks'<\/span>, chunks);\n        formData.<span class=\"hljs-title function_\">append<\/span>(<span class=\"hljs-string\">'fileId'<\/span>, uniqueFileId);\n        \n        <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-title function_\">fetch<\/span>(<span class=\"hljs-string\">'\/api\/upload-chunk'<\/span>, {\n            <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">'POST'<\/span>,\n            <span class=\"hljs-attr\">body<\/span>: formData\n        });\n        \n        <span class=\"hljs-keyword\">if<\/span> (!response.<span class=\"hljs-property\">ok<\/span>) {\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-title class_\">Error<\/span>(<span class=\"hljs-string\">`Chunk <span class=\"hljs-subst\">${i}<\/span> failed`<\/span>);\n        }\n    }\n    \n    <span class=\"hljs-comment\">\/\/ All chunks uploaded, tell server to assemble<\/span>\n    <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-title function_\">fetch<\/span>(<span class=\"hljs-string\">'\/api\/upload-complete'<\/span>, {\n        <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">'POST'<\/span>,\n        <span class=\"hljs-attr\">body<\/span>: <span class=\"hljs-title class_\">JSON<\/span>.<span class=\"hljs-title function_\">stringify<\/span>({ <span class=\"hljs-attr\">fileId<\/span>: uniqueFileId })\n    });\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Server-Side Chunked Upload Handler<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    # <span class=\"hljs-title class_\">Chunk<\/span> upload endpoint - small chunks\n    handle_path \/api\/upload-chunk {\n        request_body {\n            max_size 10MB  # <span class=\"hljs-title class_\">Each<\/span> chunk max <span class=\"hljs-number\">10<\/span> <span class=\"hljs-variable constant_\">MB<\/span>\n        }\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n\n    # <span class=\"hljs-title class_\">Finalize<\/span> endpoint - no body needed\n    handle_path \/api\/upload-complete {\n        request_body {\n            max_size 1MB\n        }\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<p class=\" text-lg my-6\"><strong>Benefits of chunked upload:<\/strong><\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Users can upload files of any size (limited by disk, not request size)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Resume capability (re-upload failed chunks, not whole file)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Better progress indication<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Server can validate each chunk<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">No need to increase request limits excessively<\/p>\n<\/li>\n<\/ul>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Complete Production-Ready Examples<\/h2>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Full-Featured Application<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\">example.<span class=\"hljs-property\">com<\/span> {\n    log {\n        output stdout\n        format json\n    }\n\n    # <span class=\"hljs-title class_\">Profile<\/span> picture upload - small\n    handle_path \/api\/users\/profile-picture {\n        request_body {\n            max_size 5MB\n        }\n\n        rate_limit {\n            zone profile_pic {\n                key {http.<span class=\"hljs-property\">request<\/span>.<span class=\"hljs-property\">header<\/span>.<span class=\"hljs-property\">Authorization<\/span>}\n                events <span class=\"hljs-number\">10<\/span>\n                <span class=\"hljs-variable language_\">window<\/span> 1d\n            }\n        }\n\n        basicauth {\n            user $2a$12$abc123...\n        }\n\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n\n    # <span class=\"hljs-title class_\">Document<\/span> upload - medium\n    handle_path \/api\/documents\/upload {\n        request_body {\n            max_size 100MB\n        }\n\n        rate_limit {\n            zone doc_upload {\n                key {http.<span class=\"hljs-property\">request<\/span>.<span class=\"hljs-property\">header<\/span>.<span class=\"hljs-property\">Authorization<\/span>}\n                events <span class=\"hljs-number\">20<\/span>\n                <span class=\"hljs-variable language_\">window<\/span> 1d\n            }\n        }\n\n        basicauth {\n            user $2a$12$abc123...\n        }\n\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n\n    # <span class=\"hljs-title class_\">Chunk<\/span> upload <span class=\"hljs-keyword\">for<\/span> large files\n    handle_path \/api\/files\/chunk {\n        request_body {\n            max_size 10MB\n        }\n\n        rate_limit {\n            zone chunk_upload {\n                key {http.<span class=\"hljs-property\">request<\/span>.<span class=\"hljs-property\">header<\/span>.<span class=\"hljs-property\">Authorization<\/span>}\n                events <span class=\"hljs-number\">1000<\/span>\n                <span class=\"hljs-variable language_\">window<\/span> 1h\n            }\n        }\n\n        basicauth {\n            user $2a$12$abc123...\n        }\n\n        reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n    }\n\n    # <span class=\"hljs-variable constant_\">API<\/span> requests - strict limit\n    handle_path \/api<span class=\"hljs-comment\">\/* {\n        request_body {\n            max_size 5MB\n        }\n\n        rate_limit {\n            zone api {\n                key {remote_host}\n                events 1000\n                window 1m\n            }\n        }\n\n        reverse_proxy localhost:3000\n    }\n\n    # Public site\n    handle {\n        request_body {\n            max_size 1MB\n        }\n\n        reverse_proxy localhost:3000\n    }\n}\n<\/span><\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<h3 class=\"text-2xl mt-10 mb-4 font-bold \">Multi-Service Setup<\/h3>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># <span class=\"hljs-variable constant_\">API<\/span> <span class=\"hljs-title class_\">Service<\/span> - strict limits\napi.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 5MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3001<\/span>\n}\n\n# <span class=\"hljs-title class_\">File<\/span> <span class=\"hljs-title class_\">Upload<\/span> <span class=\"hljs-title class_\">Service<\/span> - generous limits\nupload.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 500MB\n    }\n\n    basicauth {\n        uploader $2a$12$abc123...\n    }\n\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3002<\/span>\n}\n\n# <span class=\"hljs-title class_\">WebSocket<\/span> <span class=\"hljs-title class_\">Service<\/span> - no <span class=\"hljs-title function_\">body<\/span> (streaming)\nws.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3003<\/span>\n}\n\n# <span class=\"hljs-title class_\">Public<\/span> <span class=\"hljs-title class_\">Website<\/span> - moderate limits\nwww.<span class=\"hljs-property\">example<\/span>.<span class=\"hljs-property\">com<\/span> {\n    request_body {\n        max_size 10MB\n    }\n    reverse_proxy <span class=\"hljs-attr\">localhost<\/span>:<span class=\"hljs-number\">3000<\/span>\n}\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Key Takeaways<\/h2>\n<ol class=\"list-decimal ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Request size limits are essential<\/strong> for protecting against disk\/memory exhaustion attacks.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Set realistic limits<\/strong> based on your actual use cases, not too strict or too generous.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Protect specific endpoints<\/strong> where users upload files, with higher limits than API endpoints.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Combine with other security:<\/strong><\/p>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Rate limiting (prevent concurrent abuse)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">IP filtering (block known abusers)<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\">Authentication (identify users)<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Test your limits<\/strong> before deploying to production.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Monitor rejected requests<\/strong> via logs to identify issues or abuse.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>For very large files, use chunked uploads<\/strong> instead of increasing request limits excessively.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Document your limits<\/strong> in API documentation so clients know what to expect.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Consider user experience<\/strong> &#8211; don&#8217;t set limits so strict that legitimate use cases fail.<\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><strong>Think about disk space<\/strong> &#8211; limit how much data users can store, not just upload size.<\/p>\n<\/li>\n<\/ol>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Size Limit Quick Reference<\/h2>\n<p class=\" text-lg my-6\">Use this as a starting point for your application:<\/p>\n<div class=\"relative group\">\n<pre class=\"relative bg-[#1a1a1a] border border-gray-700 rounded-lg overflow-x-auto my-8 p-6\"><code class=\"hljs language-typescript whitespace-pre-wrap break-words text-gray-300\"># <span class=\"hljs-title class_\">Minimal<\/span> <span class=\"hljs-title function_\">API<\/span> (no uploads)\nrequest_body { max_size 1MB }\n\n# <span class=\"hljs-title class_\">Standard<\/span> web app\nrequest_body { max_size 10MB }\n\n# <span class=\"hljs-title class_\">File<\/span> upload service\nrequest_body { max_size 100MB }\n\n# <span class=\"hljs-title class_\">Video<\/span> service\nrequest_body { max_size 500MB }\n\n# <span class=\"hljs-title class_\">Professional<\/span> storage\nrequest_body { max_size 1GB }\n\n# <span class=\"hljs-title class_\">Chunked<\/span> upload per chunk\nrequest_body { max_size 10MB }\n<\/code><\/pre>\n<p><button class=\"absolute top-4 cursor-pointer right-4 p-2 rounded-md bg-[#24292e] hover:bg-gray-700 border border-gray-600 opacity-0 group-hover:opacity-100 transition-opacity duration-200\" title=\"Copy code\"><\/button><\/div>\n<hr \/>\n<h2 class=\"text-3xl font-semibold mt-14 mb-8 \">Further Reading<\/h2>\n<ul class=\"list-disc ml-6 my-6\">\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><a class=\"! !underline\" href=\"https:\/\/caddyserver.com\/docs\/caddyfile\/directives\/request_body\" target=\"_blank\" rel=\"noopener noreferrer\">Caddy Documentation &#8211; Request Body<\/a><\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><a class=\"! !underline\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Status\/413\" target=\"_blank\" rel=\"noopener noreferrer\">HTTP Status Code 413 (Payload Too Large)<\/a><\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><a class=\"! !underline\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Length\" target=\"_blank\" rel=\"noopener noreferrer\">Content-Length Header Specification<\/a><\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><a class=\"! !underline\" href=\"https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/File_Upload_Cheat_Sheet.html\" target=\"_blank\" rel=\"noopener noreferrer\">Secure File Upload Best Practices<\/a><\/p>\n<\/li>\n<li class=\" text-lg my-2\">\n<p class=\" text-lg my-6\"><a class=\"! !underline\" href=\"https:\/\/tools.ietf.org\/html\/rfc7230#section-4.1\" target=\"_blank\" rel=\"noopener noreferrer\">Chunked Transfer Encoding (RFC 7230)<\/a><\/p>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Introduction: Why Request Size Limits Matter Imagine you run a file upload service or API. One day, someone uploads a 50 GB file to your server. Your disk fills up instantly. Your server crashes. All your users can&#8217;t access the service. Or worse: A bot makes 1,000 requests, each with a 1 MB payload, consuming&#8230;<\/p>\n","protected":false},"author":1,"featured_media":4744,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[212,236],"tags":[220],"class_list":["post-4924","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops-infrastructure","category-digital-transformation","tag-web","th-blog blog-single has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/posts\/4924","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/comments?post=4924"}],"version-history":[{"count":2,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/posts\/4924\/revisions"}],"predecessor-version":[{"id":4927,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/posts\/4924\/revisions\/4927"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/media\/4744"}],"wp:attachment":[{"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/media?parent=4924"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/categories?post=4924"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.softcolon.com\/blogs\/wp-json\/wp\/v2\/tags?post=4924"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}