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]

Reply via email to