Date post: | 19-Jul-2015 |
Category: |
Software |
Upload: | marco-perone |
View: | 173 times |
Download: | 0 times |
PSR-7A SET OF COMMON INTERFACES FOR HTTP
MESSAGESby Marco Perone / @marcoshuttle
HTTP MESSAGES
HTTP MESSAGE STRUCTURE <message line> Header: value AnotherHeader: value
Message body
BODYstringhandled by server and clients as a streamPHP natively represents it using streams
REQUEST MESSAGE LINE
METHOD REQUEST-TARGET HTTP/VERSION
REQUEST TARGETorigin formabsolute formauthority formasterisk form
URI
SCHEME://AUTHORITY[/PATH][?QUERYSTRING]
AUTHORITY = [USER[:PASS]@]HOST[:PORT]
RESPONSE MESSAGE LINE
HTTP/VERSION STATUS REASON
USE OF HTTP MESSAGES IN PHP
USE CASE 1USE PHP SUPERGLOBALS
Any application before frameworks
USE CASE 2CREATE NEW IMPLEMENTATION FROM
SCRATCHFrameworks define http components
Single purpose libraries (oauth-server-php)Http clients ad Guzzle and Buzz
USE CASE 3REQUIRE A SPECIFIC HTTP CLIENT/SERVER
LIBRARY PROVIDING MESSAGEIMPLEMENTATION
Silex, Stack, Drupal 8 have hard dependencies on Symfony'sHTTP kernel
Any SDK developed with Guzzle has a hard requirement onGuzzle's HTTP message implementations
USE CASE 4CREATE ADAPTERS FOR COMMON HTTP
MESSAGE IMPLEMENTATIONSProjects such as Geocoder create redundant adapters for
common libraries
PROBLEMSSuperglobals are mutable. Libraries can alter state of theapplicationUnit and integration testing difficultProjects not capable of interoperability or cross-pollinationNecessity of building a bridge layer between applicationsAny content emitted before a call to header() will resultin that a call becoming a no-op
THE SCOPE OF PSR-7
GOALSProvide the interfaces needed for describing HTTPmessagesFocus on practical applications and usabilityDefine the interfaces to model all elements of the HTTPmessage and URI specificationsEnsure that the API does not impose arbitrary limits onHTTP messagesProvide useful abstractions both for handling incomingrequests for server-side applications and for sendingoutgoing requests in HTTP clients
NON GOALSDoes not expect all HTTP client libraries or server-sideframeworks to change their interfaces to conform. It isstrictly meant for interoperabilityShould not impose implementation details
USE CASES
CLIENTSUnified message interface to use for making requests
$response = $client>send($request);
MIDDLEWARESFunction that accepts request and response as parametersand does something with them, including delegating to the
next middleware
function ( ServerRequestInterface $request, ResponseInterface $response, callable $next = null) # do stuff here
FRAMEWORKSThey did HTTP message abstraction since a long time
PSR-7 provides a common set of interfaces
Consider Zend\Stdlib\DispatchableInterface inZend Framework 2
use Zend\Http\RequestInterface;use Zend\Http\ResponseInterface;
interface DispatchableInterface public function dispatch( RequestInterface $request, ResponseInterface $response );
PSR-7 BY EXAMPLES
INTERMEZZO: VALUE OBJECTSMessages and URIs are modeled as value objects
a change to any aspect of the message is essentially a newmessageimmutabilityensure integrity of message stateuse a base instance as prototype
MESSAGESnamespace Psr\Http\Message;
MessageInterfaceResponseInterfaceRequestInterfaceServerRequestInterface
HEADERS
// Returns null if not found:$header = $message>getHeader('Accept');
// Test for a header:if (! $message>hasHeader('Accept'))
// If the header has multiple values, fetch them// as an array:$values = $message>getHeaderLines('XFoo');
HEADERS
/* Returns the following structure: [ 'Header' => [ 'value1' 'value2' ] ]*/foreach ($message>getAllHeaders() as $header => $values)
HEADERS
$new = $message>withHeader('Location', 'http://example.com');
$message = $message>withHeader('Location', 'http://example.com');
$message = $message>withAddedHeader('XFoo', 'bar');
$message = $message>withoutHeader('XFoo');
BODIEStreated as streams
StreamableInterface is used
$body = new Stream('php://temp');$body>write('Here is the content for my message!');
$message = $message>withBody(new Stream('php://temp'));
RESPONSESstatus codereason phrase
$status = $response>getStatusCode();$reason = $response>getReasonPhrase();
$response = $response>withStatus(418, "I'm a teapot");
REQUESTSmethodrequest target
REQUEST TARGET AND URIThe request interface:
composes a UriInterface instance, which models theURI itselfprovides two methods around request-targets:getRequestTarget() andwithRequestTarget()
URI INTERFACEURI are treated as value objects
// URI parts: $scheme = $uri>getScheme(); $userInfo = $uri>getUserInfo(); $host = $uri>getHost(); $port = $uri>getPort(); $path = $uri>getPath(); $query = $uri>getQuery(); // the query STRING $authority = $uri>getAuthority(); // [userinfo@]host[:port]
$uri = $uri >withScheme('http') >withHost('example.com') >withPath('/foo/bar') >withQuery('?baz=bat');
CREATE REQUEST
$request = $request >withMethod('OPTION') >withUri($uri>withPath('/api/user')) >withRequestTarget('*');
SERVER SIDE REQUESTSPHP's Server API does a number of things for us:
Deserialization of query string arguments ($_GET)Deserialization of urlencoded form data submitted viaPOST ($_POST)Deserialization of cookies ($_COOKIE)Identification and handling of file uploads ($_FILES)Encapsulation of CGI/SAPI parameters ($_SERVER)
SERVER SIDE REQUESTSServerRequestInterface extends the base
RequestInterface and offers features around thesevalues
$query = $request>getQueryParams();$body = $request>getParsedBody();$cookies = $request>getCookieParams();$files = $request>getFileParams();$server = $request>getServerParams();
ATTRIBUTES
$request>getAttribute($name, $default = null);$request>getAttributes();$request = $request>withAttribute($name, $value);$request = $request>withoutAttribute();
REFERENCES
by
FIG PSR-7 metadocumentFIG PSR-7 specificationsPSR-7 by example @mwop