diff --git a/src/Io/SapiHandler.php b/src/Io/SapiHandler.php index fc2eeb1..461cd41 100644 --- a/src/Io/SapiHandler.php +++ b/src/Io/SapiHandler.php @@ -92,6 +92,12 @@ public function requestFromGlobals(): ServerRequestInterface } $request = $request->withParsedBody($_POST); + // Method override via POST _method "magic" parameter or X-HTTP-Method-Override header, only for POST requests + $method_override = strtoupper($_POST["_method"] ?? $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ?? ""); + if ($request->getMethod() === "POST" && in_array($method_override, ["PUT", "PATCH", "DELETE"], true)) { + $request = $request->withMethod($method_override); + } + // Content-Length / Content-Type are special <3 if ($request->getHeaderLine('Content-Length') === '') { $request = $request->withoutHeader('Content-Length'); diff --git a/tests/Io/SapiHandlerTest.php b/tests/Io/SapiHandlerTest.php index a18b390..e0db12a 100644 --- a/tests/Io/SapiHandlerTest.php +++ b/tests/Io/SapiHandlerTest.php @@ -478,4 +478,40 @@ public function testRunWillSendResponseHeadersFromDeferredHandler(): void $this->assertEquals(['Content-Type:', 'Content-Length: 0'], xdebug_get_headers()); } + + public function testRequestFromGlobalsObeysMagicMethodOverride(): void + { + header_remove(); + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_POST['_method'] = 'PUT'; + + $sapi = new SapiHandler(); + $request = $sapi->requestFromGlobals(); + + $this->assertEquals('PUT', $request->getMethod()); + } + + public function testRequestFromGlobalsObeysXHttpMethodOverrideHeader(): void + { + header_remove(); + $_SERVER['REQUEST_METHOD'] = 'POST'; + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $sapi = new SapiHandler(); + $request = $sapi->requestFromGlobals(); + + $this->assertEquals('PUT', $request->getMethod()); + } + + public function testRequestFromGlobalsIgnoresInvalidMethodOverride(): void + { + header_remove(); + $_SERVER['REQUEST_METHOD'] = 'PUT'; + $_POST['_method'] = 'POST'; + + $sapi = new SapiHandler(); + $request = $sapi->requestFromGlobals(); + + $this->assertEquals('PUT', $request->getMethod()); + } }