Skip to content

[HttpClient] Always set CURLOPT_CUSTOMREQUEST to the correct HTTP method in CurlHttpClient #59062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 2, 2024

Conversation

KurtThiemann
Copy link
Contributor

@KurtThiemann KurtThiemann commented Dec 2, 2024

Q A
Branch? 6.4
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #59043
License MIT

Currently, when sending a HEAD request and using a closure as the request body using CurlHttpClient, a PUT request instead of a HEAD request will be sent. This is because CURLOPT_NOBODY is set to make a HEAD request, but is overwritten by CURLOPT_UPLOAD, which is necessary to make curl call CURLOPT_READFUNCTION, but also sets the HTTP method to PUT.
The solution I am suggesting is to just always set CURLOPT_CUSTOMREQUEST, so the correct HTTP method will be used, no matter what other options are added.

This is mainly an issue in the PSR-18 wrapper, since PSR requests always have a request body stream, even if the body is empty. Since #58856, Psr18Client always passes a closure as the request body to the underlying HTTP client instead of just reading the entire request body stream into a string, as that made it impossible to upload large files.

While it would be possible to add an exception to Psr18Client to only add the request body if the method used commonly has a body, I think the better solution is to ensure that CurlHttpClient always actually sends the type of request that it is asked to send.

@xabbuh
Copy link
Member

xabbuh commented Dec 2, 2024

The fix looks good to me. But can we also add a test to prevent regressions?

@KurtThiemann
Copy link
Contributor Author

I added a X-Request-Vars response header to the TestHttpServer, since I can't get that info from the response body when using a HEAD request. This works locally, but seems to fail in GitHub actions.
Any ideas?

@nicolas-grekas
Copy link
Member

Thank you @KurtThiemann.

@nicolas-grekas nicolas-grekas merged commit ffc4dc6 into symfony:6.4 Dec 2, 2024
9 of 10 checks passed
@@ -197,13 +197,12 @@ public function request(string $method, string $url, array $options = []): Respo
$curlopts[\CURLOPT_RESOLVE] = $resolve;
}

$curlopts[\CURLOPT_CUSTOMREQUEST] = $method;
if ('POST' === $method) {
// Use CURLOPT_POST to have browser-like POST-to-GET redirects for 301, 302 and 303
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas wouldn't the usage of CURLOPT_CUSTOMREQUEST defeat this comment ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine because it's set after.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I, too, thought that, but after testing it just now it seems like it might not be fine...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into this, and it seems like this would be an issue in plain cURL, but actually works correctly in Symfony because redirects are handled in CurlResponse::parseHeaderLine instead of being handled by cURL itself.
I might still make a PR to add a test for this.

fabpot added a commit that referenced this pull request Dec 9, 2024
This PR was squashed before being merged into the 6.4 branch.

Discussion
----------

[HttpClient] Test POST to GET redirects

| Q             | A
| ------------- | ---
| Branch?       | 6.4
| Bug fix?      | idk
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

In a discussion in #59062 after that pull request was already merged, it was suggested that the changes of that pull request might break POST-to-GET redirects. While it turned out that they do not because of how Symfony handles redirects, but I thought it might be a good idea to just test this.

Commits
-------

a96cfa4 [HttpClient] Test POST to GET redirects
@fabpot fabpot mentioned this pull request Dec 11, 2024
This was referenced Dec 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants