PSR-7 Standard – Part 3 – Response

PSR-7 Standard – Part 3 – Response

This post is part of series:


In the last blog post we described the RequestInterface of PSR-7. Every application will process this request and returns a response to the calling client. The response is the part where a backend sends a result of an server operation back to the client. Let’s view how the ResponseInterface is designed.

/**
 * Representation of an outgoing, server-side response.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - Status code and reason phrase
 * - Headers
 * - Message body
 *
 * Responses are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ResponseInterface extends MessageInterface
{
    /**
     * Gets the response status code.
     *
     * The status code is a 3-digit integer result code of the server's attempt
     * to understand and satisfy the request.
     *
     * @return int Status code.
     */
    public function getStatusCode();

    /**
     * Return an instance with the specified status code and, optionally, reason phrase.
     *
     * If no reason phrase is specified, implementations MAY choose to default
     * to the RFC 7231 or IANA recommended reason phrase for the response's
     * status code.
     *
     * This method MUST be implemented in such a way as to retain the
     * immutability of the message, and MUST return an instance that has the
     * updated status and reason phrase.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @param int $code The 3-digit integer result code to set.
     * @param string $reasonPhrase The reason phrase to use with the
     *     provided status code; if none is provided, implementations MAY
     *     use the defaults as suggested in the HTTP specification.
     * @return static
     * @throws \InvalidArgumentException For invalid status code arguments.
     */
    public function withStatus($code, $reasonPhrase = '');

    /**
     * Gets the response reason phrase associated with the status code.
     *
     * Because a reason phrase is not a required element in a response
     * status line, the reason phrase value MAY be null. Implementations MAY
     * choose to return the default RFC 7231 recommended reason phrase (or those
     * listed in the IANA HTTP Status Code Registry) for the response's
     * status code.
     *
     * @link http://tools.ietf.org/html/rfc7231#section-6
     * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
     * @return string Reason phrase; must return an empty string if none present.
     */
    public function getReasonPhrase();
}

Like the request, the response has to be build in an immutable way. This means that every method returns a new instance of the object instead of a reference to the existing object. The interface is a lot simpler than the RequestInterface. It contains only one method withStatus to pass a HTTP status code. All the other methods are inherited by MessageInterface which we already know from RequestInterface. This is consequent, because the Request and Response are communicating trough messages. So the Request sends a message and the Response returns a message.

Using Guzzle

Like in the previous article we make use of the PSR7 library of the Guzzle project.

The installation is easy as:

composer.phar require guzzlehttp/guzzle:~6.0

We replace the “server.php” of the previous article with this code:

<?php
require_once __DIR__ . '/vendor/autoload.php';

$response = new \GuzzleHttp\Psr7\Response();
$response = $response->withStatus(200, 'OK');
$response = $response->withBody(
    \GuzzleHttp\Psr7\stream_for(
        print_r($_SERVER, true)
    )
);

echo \GuzzleHttp\Psr7\str($response);

The script is the equivalent of the server.php script of previous article where we simply dumped the $_SERVER array. Not it is HTTP compliant.

We build a new response with a status code 200 and “OK” as phrase for the HTTP status header line. According to the RequestInterface we must pass a stream as parameter. To simply convert a string we can use the stream_for function of the Guzzle library.

At the end we need to create a valid HTTP message string which can simply pushed to the client which PHP’s echo function. Guzzle provides the handy str function to convert an instance of MessageInterface to a string. We remember that the ResponseInterface extends the MessageInterface. So we can use the function and let Guzzle do the boring part.

Let’s test the server with our previous generated client.php script. Before we can test, we start the server.php with the internal PHP HTTP server:

php -S 127.0.0.1:8080 server.php

Now run the client in a second console:

php client_guzzle.php

We should now the the output of our server:

HTTP/1.1 200 OK

Array
(
    [DOCUMENT_ROOT] => /Users/cmuench/Desktop/psr-7
    [REMOTE_ADDR] => 127.0.0.1
    [REMOTE_PORT] => 57891
    [SERVER_SOFTWARE] => PHP 7.0.22 Development Server
    [SERVER_PROTOCOL] => HTTP/1.1
    [SERVER_NAME] => 127.0.0.1
    [SERVER_PORT] => 8080
    [REQUEST_URI] => /mypath?foo=bar&baz=zoz
    [REQUEST_METHOD] => GET
    [SCRIPT_NAME] => /mypath
    [SCRIPT_FILENAME] => server.php
    [PHP_SELF] => /mypath
    [QUERY_STRING] => foo=bar&baz=zoz
    [HTTP_HOST] => 127.0.0.1:8080
    [HTTP_USER_AGENT] => GuzzleHttp/6.2.1 curl/7.54.0 PHP/7.0.22
    [REQUEST_TIME_FLOAT] => 1508404883.1422
    [REQUEST_TIME] => 1508404883
)

In the next article we try to upload a file with the client to the server.

3 thoughts on “PSR-7 Standard – Part 3 – Response

Leave a Reply

Your email address will not be published. Required fields are marked *