pjfanning opened a new pull request, #1279:
URL: https://github.com/apache/pekko-http/pull/1279
### Motivation
Fixes #1278.
`BodyPartParser` carried one body part's accumulated `headers` and
`headerCount` into the next part whenever a part ended without a
header-separating empty line. In `parseHeaderLines`, the `BoundaryHeader`
branch emits the part it has just finished and then continues into the next one:
```scala
case BoundaryHeader =>
emit(BodyPartStart(headers.toList, _ => HttpEntity.empty(contentType)))
val ix = lineStart + eolConfiguration.boundaryLength
if (eolConfiguration.isEndOfLine(input, ix))
parseHeaderLines(input, ix + eolConfiguration.eolLength, headers,
headerCount, None)
```
The boundary starts a *new* part, so its header state should start empty.
`cth` was already reset to `None` on that same call, which suggests the intent
was to reset here and that `headers`/`headerCount` were simply missed.
This is long-standing and inherited from akka-http; it is not a regression.
### Modification
Start the next part with a fresh `ListBuffer` and a `headerCount` of 0.
The reset deliberately stays a direct self-call to `parseHeaderLines` rather
than being routed through a helper: that call is what makes the method
`@tailrec`, and a mutual recursion here would be unoptimised — the stack
overflow the trampoline in `parseEntity` already guards against.
### Result
Two visible effects are fixed:
- the following part was reported carrying headers it never declared;
- `headerCount` was never reset either, so a run of such parts accumulated
towards `max-header-count` across parts rather than per part, failing parts
individually well within the limit.
Measured before the fix, for a three-part entity where each part declares
one `Age` header and no separating empty line — the parts inherit each other's
headers:
```
List(Age: 12), List(Age: 12, Age: 13), List(Age: 12, Age: 13)
```
and with `max-header-count = 2`, two parts of two headers each failed
outright with `multipart part contains more than the configured limit of 2
headers`.
### Tests
Three cases added to `MultipartUnmarshallersSpec` (so each runs in both the
CRLF and LF variants):
- consecutive parts without header separation each keep their own headers;
- header counting is per part, not across parts (`max-header-count = 2`);
- a part's `Content-Type` is not carried into the next part — this one
already passed before the fix and is a regression guard for the `cth` reset
that was already correct.
Verified the first two fail on `main` and pass with the fix.
`sbt "http-tests/testOnly *MultipartUnmarshallersSpec* *MarshallingSpec
*FileUploadDirectivesSpec"` — 103 pass. Native `scalafmt` clean. No MiMa run:
the change is confined to a method body inside the anonymous `GraphStageLogic`.
### References
Fixes #1278. Noticed while reviewing #1266, which touches the same branch
but does not change this behaviour; the two do not depend on each other, though
they will conflict textually and whichever lands second will need a trivial
rebase.
🤖 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]