- Request
- How to get the Request object
- The Request Method
- The Request URI
- The Request Headers
- Get All Headers
- Get One Header
- Detect Header
- The Request Body
- Uploaded Files
- Request Helpers
- Detect XHR requests
- Content Type
- Content Length
- Server Parameter
- POST Parameters
- Route Object
- Obtain Base Path From Within Route
- Attributes
- http_get_request_body
- Parameters
- Return Values
- See Also
- User Contributed Notes 4 notes
Request
Your Slim app’s routes and middleware are given a PSR-7 request object that represents the current HTTP request received by your web server. The request object implements the PSR-7 ServerRequestInterface with which you can inspect and manipulate the HTTP request method, headers, and body.
How to get the Request object
The PSR-7 request object is injected into your Slim application routes as the first argument to the route callback like this:
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/hello', function (Request $request, Response $response) $response->getBody()->write('Hello World'); return $response; >); $app->run();
The PSR-7 request object is injected into your Slim application middleware as the first argument of the middleware callable like this:
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Slim\Factory\AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->add(function (Request $request, RequestHandler $handler) return $handler->handle($request); >); // . define app routes. $app->run();
The Request Method
Every HTTP request has a method that is typically one of:
You can inspect the HTTP request’s method with the Request object method appropriately named getMethod() .
It is possible to fake or override the HTTP request method. This is useful if, for example, you need to mimic a PUT request using a traditional web browser that only supports GET or POST requests.
To enable request method overriding the Method Overriding Middleware must be injected into your application.
There are two ways to override the HTTP request method. You can include a METHOD parameter in a POST request’s body. The HTTP request must use the application/x-www-form-urlencoded content type.
POST /path HTTP/1.1 Host: example.com Content-type: application/x-www-form-urlencoded Content-length: 22 data=value&_METHOD=PUT
You can also override the HTTP request method with a custom X-Http-Method-Override HTTP request header. This works with any HTTP request content type.
POST /path HTTP/1.1 Host: example.com Content-type: application/json Content-length: 16 X-Http-Method-Override: PUT "data":"value">
The Request URI
Every HTTP request has a URI that identifies the requested application resource. The HTTP request URI has several parts:
- Scheme (e.g. http or https )
- Host (e.g. example.com )
- Port (e.g. 80 or 443 )
- Path (e.g. /users/1 )
- Query string (e.g. sort=created&dir=asc )
You can fetch the PSR-7 Request object’s URI object with its getUri() method:
The PSR-7 Request object’s URI is itself an object that provides the following methods to inspect the HTTP request’s URL parts:
- getScheme()
- getAuthority()
- getUserInfo()
- getHost()
- getPort()
- getPath()
- getQuery() (returns the full query string, e.g. a=1&b=2 )
- getFragment()
You can get the query parameters as an associative array on the Request object using getQueryParams() .
The Request Headers
Every HTTP request has headers. These are metadata that describe the HTTP request but are not visible in the request’s body. Slim’s PSR-7 Request object provides several methods to inspect its headers.
Get All Headers
You can fetch all HTTP request headers as an associative array with the PSR-7 Request object’s getHeaders() method. The resultant associative array’s keys are the header names and its values are themselves a numeric array of string values for their respective header name.
$headers = $request->getHeaders(); foreach ($headers as $name => $values) echo $name . ": " . implode(", ", $values); >
Get One Header
You can get a single header’s value(s) with the PSR-7 Request object’s getHeader($name) method. This returns an array of values for the given header name. Remember, a single HTTP header may have more than one value!
$headerValueArray = $request->getHeader('Accept');
You may also fetch a comma-separated string with all values for a given header with the PSR-7 Request object’s getHeaderLine($name) method. Unlike the getHeader($name) method, this method returns a comma-separated string.
$headerValueString = $request->getHeaderLine('Accept');
Detect Header
You can test for the presence of a header with the PSR-7 Request object’s hasHeader($name) method.
if ($request->hasHeader('Accept')) // Do something >
The Request Body
Every HTTP request has a body. If you are building a Slim application that consumes JSON or XML data, you can use the PSR-7 Request object’s getParsedBody() method to parse the HTTP request body into a native PHP format. Note that body parsing differs from one PSR-7 implementation to another.
You may need to implement middleware in order to parse the incoming input depending on the PSR-7 implementation you have installed. Here is an example for parsing incoming JSON input:
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\MiddlewareInterface; use Psr\Http\Server\RequestHandlerInterface as RequestHandler; class JsonBodyParserMiddleware implements MiddlewareInterface public function process(Request $request, RequestHandler $handler): Response $contentType = $request->getHeaderLine('Content-Type'); if (strstr($contentType, 'application/json')) $contents = json_decode(file_get_contents('php://input'), true); if (json_last_error() === JSON_ERROR_NONE) $request = $request->withParsedBody($contents); > > return $handler->handle($request); > >
$parsedBody = $request->getParsedBody();
Technically speaking, the PSR-7 Request object represents the HTTP request body as an instance of Psr\Http\Message\StreamInterface . You can get the HTTP request body StreamInterface instance with the PSR-7 Request object’s getBody() method. The getBody() method is preferable if the incoming HTTP request size is unknown or too large for available memory.
The resultant Psr\Http\Message\StreamInterface instance provides the following methods to read and iterate its underlying PHP resource .
- getSize()
- tell()
- eof()
- isSeekable()
- seek()
- rewind()
- isWritable()
- write($string)
- isReadable()
- read($length)
- getContents()
- getMetadata($key = null)
Uploaded Files
The file uploads in $_FILES are available from the Request object’s getUploadedFiles() method. This returns an array keyed by the name of the input element.
$files = $request->getUploadedFiles();
Each object in the $files array is an instance of Psr\Http\Message\UploadedFileInterface and supports the following methods:
- getStream()
- moveTo($targetPath)
- getSize()
- getError()
- getClientFilename()
- getClientMediaType()
See the cookbook on how to upload files using a POST form.
Request Helpers
Slim’s PSR-7 Request implementation provides these additional proprietary methods to help you further inspect the HTTP request.
Detect XHR requests
You can detect XHR requests by checking if the header X-Requested-With is XMLHttpRequest using the Request’s getHeaderLine() method.
POST /path HTTP/1.1 Host: example.com Content-type: application/x-www-form-urlencoded Content-length: 7 X-Requested-With: XMLHttpRequest foo=bar
if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') // Do something >
Content Type
You can fetch the HTTP request content type with the Request object’s getHeaderLine() method.
$contentType = $request->getHeaderLine('Content-Type');
Content Length
You can fetch the HTTP request content length with the Request object’s getHeaderLine() method.
$length = $request->getHeaderLine('Content-Length');
Server Parameter
To fetch data related to the incoming request environment, you will need to use getServerParams() .
For example, to get a single Server Parameter:
$params = $request->getServerParams(); $authorization = $params['HTTP_AUTHORIZATION'] ?? null;
POST Parameters
If the request method is POST and the Content-Type is either application/x-www-form-urlencoded or multipart/form-data , you can retrieve all POST parameters as follows:
// Get all POST parameters $params = (array)$request->getParsedBody(); // Get a single POST parameter $foo = $params['foo'];
Route Object
Sometimes in middleware you require the parameter of your route.
In this example we are checking first that the user is logged in and second that the user has permissions to view the particular video they are attempting to view.
$app ->get('/course/', Video::class . ':watch') ->add(PermissionMiddleware::class);
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as RequestHandler; use Slim\Routing\RouteContext; class PermissionMiddleware public function __invoke(Request $request, RequestHandler $handler) $routeContext = RouteContext::fromRequest($request); $route = $routeContext->getRoute(); $courseId = $route->getArgument('id'); // do permission logic. return $handler->handle($request); > >
Obtain Base Path From Within Route
To obtain the base path from within a route simply do the following:
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory; use Slim\Routing\RouteContext; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/', function(Request $request, Response $response) $routeContext = RouteContext::fromRequest($request); $basePath = $routeContext->getBasePath(); // . return $response; >);
Attributes
With PSR-7 it is possible to inject objects/values into the request object for further processing. In your applications middleware often need to pass along information to your route closure and the way to do it is to add it to the request object via an attribute.
Example, Setting a value on your request object.
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as RequestHandler; $app->add(function (Request $request, RequestHandler $handler) // Add the session storage to your request as [READ-ONLY] $request = $request->withAttribute('session', $_SESSION); return $handler->handle($request); >);
Example, how to retrieve the value.
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; $app->get('/test', function (Request $request, Response $response) // Get the session from the request $session = $request->getAttribute('session'); $response->getBody()->write('Yay, ' . $session['name']); return $response; >);
The request object also has bulk functions as well. $request->getAttributes() and $request->withAttributes()
http_get_request_body
This function can not be used after http_get_request_body_stream() if the request method was another than POST.
Parameters
Return Values
Returns the raw request body as string on success or NULL on failure.
See Also
User Contributed Notes 4 notes
@slave at codegrunt dot com
If you leave out Content-Length and have no Transfer-Encoding, your request is no longer valid.
RFC261 says at chapter 4.3:
«The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request’s message-headers.»
Without those headers, the server has no way of figuring out what the length of the body is. For a response, you could indicate it with a connection close, but obviously if you do that on a request you will never get a response!
So, I assume the PhP behaviour you describe is OK as you cannot expect it to auto-magically repair all sorts of broken requests!
@Tim Trinidad
Reading php://input or using http_get_request_body_stream() must be very similar.
The documentation says:
«This function can not be used after http_get_request_body_stream() if the request method was another than POST.»
So it looks very similar to what you describe. The documentation should then read:
«This function can not be used after http_get_request_body_stream() or reading php://input, if the request method was another than POST.»
In case this saves anyone else some frustration, the «Content-Length» header decides what will be returned for «php://input». If you leave it out while testing, nothing will be returned for «php://input» or $HTTP_RAW_POST_DATA.
For example, if you are trying to test out a custom SOAP server app and you send a request like this without a Content-Length set:
——
POST /soap_service.php HTTP/1.1
Authorization: Basic abcdefgh
User-Agent: SOAPy McSOAPclient
Host: example.com
Accept: */*
MIME-Version: 1.0
Content-type: text/xml; charset=utf-8
«php://input» will always return and empty string.