pjfanning opened a new pull request, #1266: URL: https://github.com/apache/pekko-http/pull/1266
### Motivation `BodyPartParser` had no limit on how many body parts one multipart entity may contain. Each part costs a set of parsed headers and an entity of its own, so a body packed with minimal parts — a boundary, a short `Content-Disposition` and an empty body, on the order of 40–60 bytes each — amplifies the work and allocation a request of a given size causes. A body at the default `max-content-length` of 8m runs to **well over a hundred thousand parts**, all of which the strict and form-field paths materialise (a `VectorBuilder`, a field map, a `HttpEntity.Strict` per part). `max-content-length` bounds the bytes but not that amplification. Peer frameworks grew an explicit part limit for the same reason — Commons FileUpload's `FileCountLimit` (FILEUPLOAD-279), Spring's `maxParts`, Jetty's `maxFormKeys`. ### Modification Add a `max-part-count` parser setting, enforced where the parser starts the headers of a new part, failing the entity once it is exceeded. The three call sites that begin a part now go through `parsePartHeaderLines`; the recursive calls that continue the current part's headers are unaffected, as is the closing boundary, which does not start a part. ### On the default **10000 is deliberately generous, and I'd welcome a steer on it.** It is chosen to stay above the largest part count the test suite exercises — an existing case, "many small parts received in one go", that parses **5000** parts — rather than to be the tightest useful bound. It still cuts the worst case by more than an order of magnitude, and an application that knows its forms are small can set it far lower. I did not want to silently drop a documented capability for a low-severity amplification issue, which is why I sized the default around that test rather than adjusting the test. If you'd rather have a tighter default (1000 would match Jetty's form-key limit and is ample for real forms), that test can raise its own limit via config instead — say the word and I'll flip it. ### Result A multipart body can no longer be packed with an unbounded number of parts; the count is bounded by configuration. ### Tests - `sbt "http-tests/testOnly ...MultipartUnmarshallersSpec* ...MarshallingSpec ...FileUploadDirectivesSpec"` — pass (95 tests), including the existing 5000-part case. A new test configures a limit of 2, sends 3 parts and expects the entity to fail; verified it fails with the limit check disabled, in both the CRLF and LF variants. - `sbt http-core/mimaReportBinaryIssues`, `sbt http/mimaReportBinaryIssues` — pass, with an exclude for the new method on the internal `BodyPartParser.Settings` (following the existing `max-chunk-count.excludes` precedent). - `sbt "+http-core/compile"` — pass on 2.13.18 and 3.3.8. - Native `scalafmt` clean. ### References None - bounds the number of parts in a multipart entity 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
