fix(s3): return XML error responses for presigned POST failures#13
Open
fix(s3): return XML error responses for presigned POST failures#13
Conversation
Presigned POST errors (e.g. policy condition failures) were being thrown as AwsException and caught by the global AwsExceptionMapper, which returns JSON. Real AWS S3 and LocalStack return XML error responses for presigned POST operations. Wrap handlePresignedPost in a try/catch that converts AwsException to XML via xmlErrorResponse(), matching the AWS/LocalStack behavior. Co-Authored-By: Matej Snuderl <ematej.snuderl@gmail.com>
Original prompt from Matej
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Adds a test that extracts the raw response body and asserts it contains the exact XML substring that downstream consumers (e.g. seadn) expect: <Code>AccessDenied</Code><Message>Invalid according to Policy: ... ["eq", "$Content-Type", "image/png"]</Message> This complements the existing hasXPath-based assertions which auto- unescape XML entities and therefore don't verify the wire format. Co-Authored-By: Matej Snuderl <ematej.snuderl@gmail.com>
Meemaw
commented
Apr 10, 2026
|
|
||
| // Verify the raw XML contains the expected structure with XML-escaped quotes. | ||
| // This is the exact substring that the seadn test suite asserts against. | ||
| assertThat(responseBody, containsString( |
Member
Author
There was a problem hiding this comment.
Can we assert exact string?
There was a problem hiding this comment.
Updated — now asserts the exact full XML response with matchesRegex. The only dynamic part is RequestId (random UUID), matched with a regex pattern. Everything else is asserted literally including the " encoding, XML declaration, and element structure.
Replace containsString with matchesRegex to assert the full XML response structure. The only dynamic part is RequestId (random UUID), matched with a regex pattern. Co-Authored-By: Matej Snuderl <ematej.snuderl@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Presigned POST error responses (e.g. policy condition failures like content-type mismatch) are currently thrown as
AwsException, which propagates to the globalAwsExceptionMapperand is serialized as JSON. Real AWS S3 and LocalStack return XML error responses for presigned POST operations.This wraps
handlePresignedPostin a try/catch that convertsAwsExceptionto XML via the existingxmlErrorResponse()helper.Type of change
fix:)feat:)feat!:orfix!:)AWS Compatibility
AWS S3 presigned POST error responses use the standard XML error format:
The global
AwsExceptionMapperreturns JSON, which breaks clients (including the AWS SDK) that expect XML.Updates since last revision
presignedPostReturnsXmlErrorResponseBodyintegration test that asserts the exact XML wire format usingmatchesRegex(onlyRequestIdis dynamic). This verifies the full response including"-encoded quotes in the<Message>element, matching what downstream consumers (e.g. seadn) parse from the raw response body.xmlErrorResponsestatus code handling — verify it respects the status code fromAwsException(e.g. 403 forAccessDenied, 400 forInvalidArgument) rather than defaulting to a fixed code."encoding — the XML builder encodes double quotes as"in element text. The new test asserts this exact encoding in the raw response. Confirm this matches real AWS S3 behavior (it does per the XML spec, and LocalStack produces the same output).Checklist
./mvnw testpasses locallyLink to Devin session: https://app.devin.ai/sessions/06b7e28f3e664783b17ed18060e5c267
Requested by: @Meemaw