The Request
最后更新于:2022-04-01 04:24:26
# Request
[TOC=2,3]
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](http://www.php-fig.org/psr/psr-7/#3-2-1-psr-http-message-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:
~~~
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
$app = new \Slim\App;
$app->get('/foo', function (ServerRequestInterface $request, ResponseInterface $response) {
// Use the PSR 7 $request object
return $response;
});
$app->run();
~~~
Figure 1: Inject PSR 7 request into application route callback.
The PSR 7 request object is injected into your Slim application *middleware* as the first argument of the middleware callable like this:
~~~
<?php
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
$app = new \Slim\App;
$app->add(function (ServerRequestInterface $request, ResponseInterface $response, callable $next) {
// Use the PSR 7 $request object
return $next($request, $response);
});
// Define app routes...
$app->run();
~~~
Figure 2: Inject PSR 7 request into application middleware.
## The Request Method
Every HTTP request has a method that is typically one of:
* GET
* POST
* PUT
* DELETE
* HEAD
* PATCH
* OPTIONS
You can inspect the HTTP request’s method with the Request object method appropriately named `getMethod()`.
~~~
$method = $request->getMethod();
~~~
Because this is a common task, Slim’s built-in PSR 7 implementation also provides these proprietary methods that return `true` or `false`.
* `$request->isGet()`
* `$request->isPost()`
* `$request->isPut()`
* `$request->isDelete()`
* `$request->isHead()`
* `$request->isPatch()`
* `$request->isOptions()`
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.
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
~~~
Figure 3: Override HTTP method with _METHOD parameter.
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"}
~~~
Figure 4: Override HTTP method with X-Http-Method-Override header.
You can fetch the *original* (non-overridden) HTTP method with the PSR 7 Request object’s method named `getOriginalMethod()`.
## 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 with its `getUri()` method:
~~~
$uri = $request->getUri();
~~~
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()`
* `getHost()`
* `getPort()`
* `getPath()`
* `getBasePath()`
* `getQuery()` (returns string)
* `getQueryParams()` (returns associative array)
Base Path
If your Slim application's front-controller lives in a physical subdirectory beneath your document root directory, you can fetch the HTTP request's physical base path (relative to the document root) with the Uri object's `getBasePath()` method. This will be an empty string if the Slim application is installed in the document root's top-most directory.
## 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);
}
~~~
Figure 5: Fetch and iterate all HTTP request headers as an associative array.
### 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');
~~~
Figure 6: Get values for a specific HTTP header.
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');
~~~
Figure 7: Get single header's values as comma-separated string.
### 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
}
~~~
Figure 8: Detect presence of a specific HTTP request header.
## 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. Slim can parse JSON, XML, and URL-encoded data out of the box.
~~~
$parsedBody = $request->getParsedBody();
~~~
Figure 9: Parse HTTP request body into native PHP format
* JSON requests are converted into a PHP object with `json_decode($input)`.
* XML requests are converted into a `SimpleXMLElement` with`simplexml_load_string($input)`.
* URL-encoded requests are converted into a PHP array with `parse_str($input)`.
Technically speaking, Slim’s 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.
~~~
$body = $request->getBody();
~~~
Figure 10: Get HTTP request body
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)`
## 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 with the Request object’s `isXhr()` method. This method detects the presence of the `X-Requested-With` HTTP request header and ensures its value is`XMLHttpRequest`.
~~~
POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 7
X-Requested-With: XMLHttpRequest
foo=bar
~~~
Figure 11: Example XHR request.
~~~
if ($request->isXhr()) {
// Do something
}
~~~
### Content Type
You can fetch the HTTP request content type with the Request object’s `getContentType()`method. This returns the `Content-Type` header’s full value as provided by the HTTP client.
~~~
$contentType = $request->getContentType();
~~~
### Media Type
You may not want the complete `Content-Type` header. What if, instead, you only want the media type? You can fetch the HTTP request media type with the Request object’s`getMediaType()` method.
~~~
$mediaType = $request->getMediaType();
~~~
You can fetch the appended media type parameters as an associative array with the Request object’s `getMediaTypeParams()` method.
~~~
$mediaParams = $request->getMediaTypeParams();
~~~
### Character Set
One of the most common media type parameters is the HTTP request character set. The Request object provides a dedicated method to retrieve this media type parameter.
~~~
$charset = $request->getContentCharset();
~~~
### Content Length
You can fetch the HTTP request content length with the Request object’s `getContentLength()`method.
~~~
$length = $request->getContentLength();
~~~
### IP Address
You can fetch the HTTP request’s source IP address with the Request object’s `getIp()`method. This method respects the `X-Forwarded-For` header, if present.
~~~
$ip = $request->getIp();
~~~