Apabila muat naik PDF besar ditolak: had 100 MiB pada badan permintaan dan ralat yang menunjuk ke arah salah
Satu badan permintaan boleh mencapai 100 MiB, iaitu 104,857,600 bait, termasuk pembingkaian multipart. Melebihi had itu, endpoint operasi menjawab 400 dengan kod bad_request, bukan 413, jadi masalah saiz terbaca seperti masalah parameter. Dengan Idempotency-Key ada had 100 MiB kedua pada penimbal respons; melewatinya anda mendapat 500 dan tiada apa-apa dicache.

PDF besar yang gagal dimuat naik biasanya bukan fail yang rosak. Badan permintaan melanggar had satu permintaan: 100 MiB, atau 104,857,600 bait. Ia diukur merentas seluruh badan, termasuk sempadan multipart dan pengepala medan, dan angka tepat itu lulus manakala satu bait lagi ditolak.
Ralat yang dipulangkan menunjuk ke arah lain. Endpoint operasi menjawab 400 dengan code ditetapkan kepada bad_request dan butiran yang menyatakan satu medan multipart gagal dibaca, tanpa sebarang sebutan tentang saiz. Klien yang bercabang pada code mengelaskannya sebagai ralat parameter lalu pergi menyemak nama medan, sedangkan yang perlu diubah ialah saiz fail.
100 MiB yang sama turut mengawal arah bertentangan. Permintaan yang membawa Idempotency-Key membaca respons ke dalam memori sebelum menyimpannya dalam cache, terhadap angka yang sama, dan apabila melewatinya pemanggil menerima 500 sedangkan operasi itu sudah selesai. Satu angka, dua mod kegagalan yang bertentangan.
100 MiB = 104,857,600 bait (angka tepat ini lulus)
|
+------------------+------------------+
| |
masuk (badan permintaan) keluar (badan respons)
seluruh badan, sempadan multipart hanya dengan Idempotency-Key,
dan pengepala medan termasuk; satu cache miss dan upstream 2xx
operasi dan pipeline berkongsinya
melebihi: 400 + bad_request melebihi: 500, tiada apa dicache
(butiran: satu medan multipart gagal dibaca)
Nota rajah: satu had, dan sisi masuk serta sisi keluar daripadanya memulangkan kod status berbeza dengan akibat yang bertentangan.
Had ini mengira seluruh badan permintaan, termasuk sempadannya
100 MiB mengehadkan badan satu permintaan, bukan saiz satu fail dan bukan saiz selepas penyahmampatan.
- Satu operasi dan pipeline berbilang langkah berkongsi angka itu. Memecahkan kerja kepada 10 langkah dalam satu panggilan
/api/v1/pipelinetidak menjadikan silingnya 1 GB; bilangan langkah hanya mempengaruhi masa jalan. - Angka sempadan itu sendiri lulus: badan permintaan 104,857,600 bait diteruskan, 104,857,601 bait tidak.
- Badan membawa pengepala setiap medan dan pembatas sempadan selain bait fail, jadi peruntukan yang tinggal untuk satu fail adalah ketat di bawah 100 MiB. Fail bersaiz tepat 104,857,600 bait ditolak.
Perkara terakhir itulah yang paling mudah tersasar dalam amalan: curl -F menambah sempadan untuk anda, jadi membandingkan saiz fail dengan garis itu tidak akan pernah tepat.
Melebihi had anda mendapat 400 dan bad_request
Respons yang melebihi had tidak menggunakan 413, dan tidak membawa sebarang perkataan tentang saiz. Ulangi dengan badan satu bait melebihi had:
head -c 104857601 /dev/zero > /tmp/over.bin
curl -s -X POST "$API_BASE/api/v1/misc/compress-pdf" \
-H "X-API-KEY: $API_KEY" \
-F "fileInput=@/tmp/over.bin"
HTTP/1.1 400 Bad Request
content-type: application/problem+json
{ "code": "bad_request",
"detail": "failed to read multipart field: Error parsing `multipart/form-data` request",
"hint": "Fix request parameters or upload a valid PDF.",
"status": 400,
"title": "Bad Request",
"type": "https://pdf123.xyz/developers/errors#bad_request" }
Tiga perkara untuk dibaca bersama:
- Statusnya 400. Kegagalan membaca badan dikelaskan sebagai
bad_requestdi sini dan tetap melalui problem+json, jadi klien yang ditulis untuk "melebihi had bermakna 413" mengambil cabang yang salah. codeialahbad_request, satu entri sebenar dalam jadual kod ralat. Ia tidak jatuh ke pengendali menyeluruh; ia berkongsi satu kod dengan nama medan yang tersalah taip atau pengekodan multipart yang rosak, dan tiada apa-apa dalam jadual itu menyentuh saiz.hintmemberitahu anda memuat naik PDF yang sah. Fail yang anda muat naik sangat mungkin PDF yang sah yang kebetulan beberapa ratus bait terlalu besar.
Petunjuknya, jadi, bukan kod status tetapi jumlah bait badannya: pada 400 yang detail-nya mengandungi failed to read multipart field, ukur saiznya seterusnya daripada menelusuri semula borang.
413 memang berlaku di tapak ini, cuma bukan pada endpoint operasi. Setiap titik masuk yang menerima muat naik fail telah dinaikkan kepada 100 MiB, manakala endpoint yang tidak menerima muat naik masih berjalan pada lalai 2 MiB kerangka HTTP (axum Rust), di mana badan yang melebihi had mendapat 413 dan satu baris teks biasa:
head -c 2097153 /dev/zero > /tmp/big.json
curl -s -w '\n%{http_code}\n' -X POST "$API_BASE/api/v1/auth/login" \
-H 'Content-Type: application/json' \
--data-binary @/tmp/big.json
Failed to buffer the request body: length limit exceeded
413
Satu fakta, dua kod status dan dua badan respons bergantung pada endpoint. Membawa mana-mana pengalaman itu merentas ke yang lain akan mengelirukan anda.
Kegagalan lain dengan angka yang sama, pada arah pulang
Permintaan dengan Idempotency-Key menyimpan responsnya dalam cache supaya percubaan semula boleh memainkannya kembali. Menyimpan dalam cache bermakna membaca badan respons ke dalam memori dahulu, dan bacaan itu dihadkan oleh 100 MiB yang sama, walaupun ia memerlukan syarat yang jauh lebih sempit:
- Permintaan membawa
Idempotency-Key - Cache terlepas, jadi kunci ini baharu
- Operasi huluan memulangkan 2xx
Respons yang gagal tidak dicache dan terus melalui, jadi hanya output besar yang berjaya sampai ke had ini.
Apa yang berlaku di situ ialah perkara yang wajar diingati: anda mendapat 500, dan tiada apa-apa ditulis ke cache. Operasi itu sudah berjalan, namun pemanggil melihat kegagalan; kerana tiada apa-apa dicache, percubaan semula menjalankan keseluruhannya sekali lagi. Kunci idempotensi wujud untuk menghapuskan kerja berulang tetapi gagal tepat ketika paling diperlukan, dengan mengemas kerja yang sudah siap sebagai kesalahan pelayan. Cache ini hidup dalam memori proses dan tidak pernah ditulis ke cakera, jadi permulaan semula akan menghapuskannya; untuk semantiknya lihat Idempotency-Key: Cubaan Semula yang Selamat untuk Tugasan PDF.
100 MiB bukan tetapan platform yang boleh dikonfigurasi
Angka itu tidak boleh diubah. Tiada pemboleh ubah persekitaran menaikkan atau menurunkannya, ke arah mana pun; angka lain bermakna mengubah kod dan membina semula imej. Carilah ia sebagai tetapan penerapan dan anda tidak akan menemukannya.
Ia juga lebih daripada sekadar kuota. Bait badan permintaan dibaca sepenuhnya ke dalam memori sebelum diproses, jadi setiap muat naik besar yang serentak menyimpan jumlah yang sebanding di sisinya. Menaikkan siling bermakna menerima puncak memori yang lebih tinggi bersamanya: angka itu juga yang menahan satu permintaan daripada menyeret proses itu ke bawah.
Penerapan hos sendiri secara lalai tiada proksi songsang, dan portal tidak memeriksa saiz sebelum menyerahkan, jadi penolakan itu datang daripada had pelayan itu sendiri. Letakkan nginx di hadapan dan anda akan melanggar nginx dahulu: client_max_body_size hanya membenarkan 1 MiB secara lalai dan menjawab 413, bentuk yang hampir sama dengan perbandingan di atas dan mudah disangka sebagai had yang sama.
Apa yang perlu dilakukan apabila melanggarnya
Daripada yang paling murah:
- Ukur sebelum menghantar. Bandingkan jumlah bait badan permintaan dengan 104,857,600 sebelum permintaan keluar, dan sediakan ruang untuk sempadan. Itu lebih baik daripada membaca kod status selepasnya.
- Mampatkan fail sehingga di bawah had. Saiz imbasan sebahagian besarnya datang daripada lapisan imejnya, dan memampatkan semula biasanya membuang sebahagian yang ketara. Mampatkan PDF berjalan dalam pelayar, tidak perlu skrip.
- Pecahkan kerja kepada beberapa panggilan. Apabila kandungannya boleh dibahagi, Asingkan PDF dan hantarnya dalam beberapa permintaan: kurang menyusahkan daripada menaikkan siling, dan ia tidak menaikkan memori yang dipegang satu permintaan.
- Ubah had hanya untuk keperluan satu permintaan yang keras. Itu bermakna mengubah kod dan membina semula, serta menerima kos memori daripada bahagian sebelumnya.
Had ini menuntut klien membuat keputusan lebih awal
Kedua-dua kegagalan menunjuk kepada satu kesimpulan: angka 100 MiB perlu dikira oleh klien sendiri sebelum menghantar. Di sisi masuk, anda dijawab dengan bad_request, kod yang tidak berkata apa-apa tentang saiz; di sisi keluar, dengan 500, yang kelihatan seperti kesalahan pelayan. Mengira bait sebelum permintaan keluar ialah satu-satunya cara menilai yang tidak bergantung pada apa yang dikatakan mesej ralat.