Response

An overview of the http response object

Overview

HTTP Response Object

An HTTP response object represents the current HTTP response to be returned to the client. The response object implements the PSR-7 ResponseInterface with which you can inspect and manipulate the HTTP response status, headers, and body.

BitFrame supports both, PSR-7 and PSR-15 style coding patterns. For the former, an http response object is supplied to the controller as the second argument, while for the latter a response object is returned from the previously run/handled middleware. The main difference between the two approaches is the way response is handled. The PSR-7 way of injecting response into each middleware in the queue can be problematic because in the PSR-7 model, middlewares pass the response from one to the other down the queue, where at any point an outer middleware can make a change to the response object passing it down to others in the queue. The general expection is that it's going to propagate back out, but what if an inner middleware returns a different response entirely? This could lead to unexpected results, which is why if a middleware needs to operate on a response, it should operate on the response returned by another middleware (as it's done in PSR-15 based approach).

A BitFrame response object has methods implemented from the following interfaces:

As per PSR-7 standard directive \Psr\Http\Message\ResponseInterface extends \Psr\Http\Message\MessageInterface, therefore, a typical PSR-7 response object would have methods implemented from both of these interfaces.

Accessing The Response:
PSR-15 Approach:

In a PSR-15 approach, the http requests are handled and the response is returned to other middlewares down the order. You can retrieve the http response by any of the following methods:

  1. Calling the getResponse() method on the \BitFrame\Application instance;
  2. Inside a MiddlewareInterface class, handling a request and receiving an http response object when a middleware finishes processing a request. For example:
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Server\RequestHandlerInterface as Handler;
use \Psr\Http\Message\ResponseInterface as Response;
use \Psr\Http\Server\MiddlewareInterface;

class SomeMiddleware implements MiddlewareInterface
{
    public function process(Request $request, Handler $handler): Response
    {
        // 1. handle previous requests and return a response
        $response = $handler->handle($request);

        // 2. do something
        $response->getBody()->write("Hello World!");

        // 3. return response
        return $response;
    }
}
PSR-7 Approach:

For PSR-7 approaches, the response object is injected into your route controllers as the second argument like so:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

$app = new \BitFrame\Application;

$app->get('/', function(Request $request, Response $response, callable $next) {
    // do something
});

Similarly, the middleware callback/handler/controller also gets the response object as the second argument, for example:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;

$app = new \BitFrame\Application;

$app->addMiddleware(function(Request $request, Response $response, callable $next) {
    // do something
});

You may choose to use other ways to handle middlewares and to handle routes as shown in our guides.

Helper Methods:

Response objects created via \BitFrame\Factory\HttpMessageFactory (which is what's done internally in BitFrame by default) or response objects that use \BitFrame\Message\ResponseTrait provide the following proprietary (non-standard) helper methods:

The use of these helper methods is strictly optional as they are merely meant as shortcuts to things you can just as easily accomplish without using them. If you do not wish to use default libraries (as coded into the BitFrame factories), you should avoid using these methods as they're not a part of the PSR standard. As an alternative, you could look at each individual method's source to see how they go about doing things, and can use the code in there as a substitute to using the proprietary methods.

Using get_class() function on http response objects created via the \BitFrame\Factory\HttpMessageFactory would return an anonymous class because internally, we've used an anonymous class to extend functionality of response objects for the libraries we support by default. You could instead use instanceof to validate the class instance or alternatively, you could view our guide on customizing BitFrame which has details on various ways you could replace the default response factory/class.

Response Statuses

Every HTTP response message has a status code, a 3-digit numeric value that identifies the type of HTTP response to be returned to the client. To get a response object's status code, you can call the getStatusCode() method on a ResponseInterface instance like so:

$status = $response->getStatusCode();

The PSR-7 response object also provides a getReasonPhrase() method which allows us to get the response reason phrase associated with the status code, like so:

$reason = $response->getReasonPhrase();

If during the lifecycle of handling an http request, you decide to add a custom status code (and optionally a reason phrase), you could do so using the withStatus() method on a ResponseInterface instance with the specified status code and, optionally, reason phrase. For example:

$newResponse = $response->withStatus(404, 'Whoops! Not Found');

Calling this method returns a new copy of the response object with the specified status and, optionally, reason phrase. This is so because the response object is immutable.

Response Headers

Every HTTP response has headers. The response headers are metadata that describe the HTTP response. These headers are not visible in the response's body.

To get a complete list of header-related methods, see the PSR-7 interfaces implemented by a PSR-7 http response object.

Get All Headers:

You can get all the request headers by using the getHeaders() method on the response object like so:

$headers = $response->getHeaders();
foreach ($headers as $name => $values) {
    echo $name . ": " . implode(", ", $values);
}
Get Single Header:

Similarly, to retrieve a single header value, you could use the getHeader() like so:

// $name of the header
$response->getHeader($name);

The return value for the getHeader() method is an array, since a single HTTP header may have more than one value. If the header does not exist, an empty array is returned.

You may also fetch a comma-separated string with all the values for a given header by calling the getHeaderLine() method on the response object like so:

// $name of the header
$request->getHeaderLine($name);
Check If Header Exists:

We could also check if a header exists by using the hasHeader() method like so:

// $name of the header
$request->hasHeader($name);
Setting A Header Value:

You may set a header value by calling the withHeader() method on the response object like so:

// $name of the header + its $value
$newResponse = $response->withHeader($name, $value);

Calling this method returns a new copy of the response object with the specified header. This is so because the response object is immutable.

Remove A Header:

Similarly, you could remove a header by calling the withoutHeader() method on the response object like so:

// $name of the header
$newResponse = $response->withoutHeader($name);

Calling this method returns a new copy of the response object without the specified header. This is so because the response object is immutable.

Response Body

Every HTTP response message has a body which can consist of any content. The getBody() method can be used to retrieve the HTTP response's body content which returns an instance of \Psr\Http\Message\StreamInterface, for example:

$body = $response->getBody();

See \Psr\Http\Message\StreamInterface to get a complete list of methods available.

Comments

Let us know if you have something to say or add