Skip to content

fix: drop Content-Type: application/json preset so multipart uploads work#12

Open
ViT4RGh0ST wants to merge 1 commit into
mainfrom
fix/multipart-content-type-preset
Open

fix: drop Content-Type: application/json preset so multipart uploads work#12
ViT4RGh0ST wants to merge 1 commit into
mainfrom
fix/multipart-content-type-preset

Conversation

@ViT4RGh0ST

Copy link
Copy Markdown

Summary

The client pre-set Content-Type: application/json on the shared PendingRequest (and again in sendRequest and pool), which silently broke the file-upload flow recommended in the README:

SapB1::sendRequestWithCallback(fn ($http) => $http
    ->attach('my_file', file_get_contents('/path/to/file.pdf'), 'file.pdf')
    ->post('Attachments2'));

Guzzle only applies its own Content-Type: multipart/form-data; boundary=... when no Content-Type is already set (see GuzzleHttp\Client::applyOptions). The preset kept application/json stuck on multipart requests, so SAP B1 Service Layer received a multipart body under a JSON content type and rejected it with BadFormat (code -1).

Why it's safe
Laravel's HTTP client already defaults the body format to json and Guzzle conditionally sets Content-Type: application/json when the request has a JSON body — so normal CRUD calls (post, patch, put) keep sending Content-Type: application/json as before. Accept: application/json is preserved.

Test plan
Added regression test: it sendRequestWithCallback supports multipart uploads without Content-Type collision
Full suite passes: 154 tests, 319 assertions
Pint + PHPStan clean

…work

The client pre-set Content-Type: application/json on the shared PendingRequest
(and again in sendRequest and pool), which silently broke the file-upload flow
recommended in the README:

    SapB1::sendRequestWithCallback(fn ($http) => $http
        ->attach('my_file', file_get_contents(...), 'file.pdf')
        ->post('Attachments2'));

Guzzle only applies its own `Content-Type: multipart/form-data; boundary=...`
when no Content-Type is already set (see GuzzleHttp\Client::applyOptions).
The preset kept `application/json` stuck on multipart requests, so SAP B1
Service Layer received a multipart body under a JSON content type and rejected
it with `BadFormat`.

Removing the preset is safe because Laravel's HTTP client already defaults
the body format to JSON and Guzzle conditionally sets the matching
Content-Type for JSON payloads — so normal CRUD calls still send
`Content-Type: application/json` as before. Accept: application/json is
preserved.

Adds a regression test covering the attach() + post() flow so the preset
doesn't creep back in.
@ViT4RGh0ST ViT4RGh0ST requested a review from AlexR1712 April 20, 2026 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant