[php-src] Issue #11274: POST/PATCH request via file_get_contents + stream_context_create switches to GET after a HTTP 308 redirect

From: Date: Fri, 19 May 2023 09:25:10 +0000
Subject: [php-src] Issue #11274: POST/PATCH request via file_get_contents + stream_context_create switches to GET after a HTTP 308 redirect
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-244487@lists.php.net to get a copy of this message
Issue: https://github.com/php/php-src/issues/11274 Author: ThiefMaster ### Description The following code: ```php <?php echo file_get_contents('http://127.0.0.1:8080/test', false, stream_context_create(['http' => ['method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query(['hello' => 'world'])]])); echo file_get_contents('http://127.0.0.1:8080/test', false, stream_context_create(['http' => ['method' => 'PATCH', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query(['hello' => 'world'])]])); echo file_get_contents('http://127.0.0.1:8080/test/', false, stream_context_create(['http' => ['method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query(['hello' => 'world'])]])); echo file_get_contents('http://127.0.0.1:8080/test/', false, stream_context_create(['http' => ['method' => 'PATCH', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query(['hello' => 'world'])]])); ``` Resulted in this output: ```json {"method":"GET"} {"method":"GET"} {"hello":"world","method":"POST"} {"hello":"world","method":"PATCH"} ``` But I expected this output instead: ```json {"hello":"world","method":"POST"} {"hello":"world","method":"PATCH"} {"hello":"world","method":"POST"} {"hello":"world","method":"PATCH"} ``` The server on 127.0.0.1:8080 is this small Flask app (I'm not really a PHP person anymore so I couldn't be bothered to use PHP for this after not having written any PHP code in the last 15 or so years ;)): ```python from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/test/', methods=['GET', 'POST', 'PATCH']) def test(): return jsonify(method=request.method, **request.form) app.run(port=8080) ``` When sending a request to the URL without the trailing slash, it uses a HTTP 308 redirect to redirect to the URL with that slash. Clients are required to keep the method and payload when encountering such a redirect: See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308): > The request method and the body will not be altered, whereas > [301](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301) may incorrectly sometimes be > changed to a [GET](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) method. And even [RFC7538](https://www.rfc-editor.org/rfc/rfc7538.txt) specifying this status code: > Note: This status code is similar to 301 (Moved Permanently) ([RFC7231], Section 6.4.2), except > that it does **not allow changing the request method from POST to GET**. ### PHP Version 8.2.6 ### Operating System _No response_

« previous php.bugs (#244487) next »