Transcript
  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    1/22

    PHP-FIGHomeRecommendations (PSRs)MembersBylawsFAQsGet InvolvedPSR-7:HTTP Message Meta DocumentPSR-7:HTTP Message Meta Document

    1. Summary

    The purpose of thisproposal isto provide a set of common interfacesfor

    HTTP messagesasdescribedin RFC 7230andRFC 7231, andURIsasdescribed

    in RFC 3986(in the context of HTTP messages).

    RFC 7230: http://www.ietf.org/rfc/rfc7230.txt

    RFC 7231: http://www.ietf.org/rfc/rfc7231.txt

    RFC 3986: http://www.ietf.org/rfc/rfc3986.txt

    All HTTP messagesconsist of the HTTP protocol version being used, headers,

    anda message body. A Requestbuildson the message to include the HTTPmethodusedto make the request, andthe URIto which the request ismade.

    A Responseincludesthe HTTP statuscode andreason phrase.

    In PHP, HTTP messagesare usedin two contexts:

    To sendan HTTP request, via the ext/curl extension, PHP'snative stream

    layer, etc., andprocessthe receivedHTTP response. In otherwords, HTTPmessagesare usedwhen using PHP asan HTTP client.

    To processan incoming HTTP request to the server, andreturn an HTTP

    response to the client making the request. PHP can use HTTP messages

    when usedasa server-side applicationto fulfill HTTP requests.

    Thisproposal presentsan APIforfully describing all partsof the variousHTTP

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    2/22

    messageswithin PHP.

    2. HTTP Messagesin PHP

    PHP doesnot have built-in support forHTTP messages.

    Client-side HTTP support

    PHP supportssending HTTP requestsvia several mechanisms:

    PHP streams

    The cURL extension

    ext/http(v2also attemptsto addressserver-side support)

    PHP streamsare the most convenient andubiquitousway to sendHTTP

    requests, but pose a numberof limitationswith regardsto properly

    configuring SSL support, andprovide a cumbersome interface aroundsetting

    thingssuch asheaders. cURL providesa complete andexpandedfeature-set,

    but, asit isnot a default extension, isoften not present. The http extension

    suffersfrom the same problem ascURL, aswell asthe fact that it has

    traditionally hadfarfewerexamplesof usage.

    Most modern HTTP client librariestendto abstract the implementation, to

    ensure they can work on whateverenvironment they are executedon, and

    acrossany of the above layers.

    Server-side HTTP Support

    PHP usesServerAPIs(SAPI) to interpret incoming HTTP requests, marshal

    input, andpassoff handling to scripts. The original SAPIdesign mirrored

    Common Gateway Interface, which wouldmarshal request data andpush it

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    3/22

    into environment variablesbefore passing delegation to a script; the script

    wouldthen pull from the environment variablesin orderto processthe

    request andreturn a response.

    PHP'sSAPIdesign abstractscommon input sourcessuch ascookies, query

    string arguments, andurl-encodedPOST content via superglobals( $_COOKIE ,

    $_GET , and $_POST , respectively), providing a layerof convenience forweb

    developers.

    On the response side of the equation, PHP wasoriginally developedasa

    templating language, andallowsintermixing HTML andPHP; any HTML

    portionsof a file are immediately flushedto the output buffer. Modernapplicationsandframeworkseschewthispractice, asit can leadto issues

    with regardsto emitting a statusline and/orresponse headers; they tendto

    aggregate all headersandcontent, andemit them at once when all other

    application processing iscomplete. Special care needsto be paidto ensure

    that errorreporting andotheractionsthat sendcontent to the output buffer

    do not flush the output buffer.

    3. Why Bother?

    HTTP messagesare usedin a wide numberof PHP projects-- both clientsand

    servers. In each case, we observe one ormore of the following patternsor

    situations:

    Projectsuse PHP'ssuperglobalsdirectly.1.

    Projectswill create implementationsfrom scratch.2.

    Projectsmay require a specific HTTP client/serverlibrary that provides

    HTTP message implementations.

    3.

    Projectsmay create adaptersforcommon HTTP message4.

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    4/22

    implementations.

    Asexamples:

    Just about any application that began development before the rise of

    frameworks, which includesa numberof very popularCMS, forum, andshopping cart systems, have historically usedsuperglobals.

    1.

    Frameworkssuch asSymfony andZendFramework each define HTTP

    componentsthat form the basisof theirMVC layers; even small, single-

    purpose librariessuch asoauth2-server-php provide andrequire their

    own HTTP request/response implementations. Guzzle, Buzz, andother

    HTTP client implementationseach create theirown HTTP message

    implementationsaswell.

    2.

    Projectssuch asSilex, Stack, andDrupal 8have harddependencieson

    Symfony'sHTTP kernel. Any SDK built on Guzzle hasa hardrequirement

    on Guzzle'sHTTP message implementations.

    3.

    Projectssuch asGeocodercreate redundant adaptersforcommon

    libraries.

    4.

    Direct usage of superglobalshasa numberof concerns. First, these are

    mutable, which makesit possible forlibrariesandcode to alterthe values,

    andthusalterstate forthe application. Additionally, superglobalsmake unit

    andintegration testing difficult andbrittle, leading to code quality

    degradation.

    In the current ecosystem of frameworksthat implement HTTP messageabstractions, the net result isthat projectsare not capable of interoperability

    orcross-pollination. In orderto consume code targeting one framework from

    another, the first orderof businessisbuilding a bridge layerbetween the

    HTTP message implementations. On the client-side, if a particularlibrary

    doesnot have an adapteryoucan utilize, youneedto bridge the

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    5/22

    request/response pairsif youwish to use an adapterfrom anotherlibrary.

    Finally, when it comesto server-side responses, PHP getsin itsown way: any

    content emittedbefore a call to header() will result in that call becoming a

    no-op; depending on errorreporting settings, thiscan often mean headers

    and/orresponse statusare not correctly sent. One way to work aroundthisis

    to use PHP'soutput buffering features, but nesting of output bufferscan

    become problematic anddifficult to debug. Frameworksandapplications

    thustendto create response abstractionsforaggregating headersand

    content that can be emittedat once - andthese abstractionsare often

    incompatible.

    Thus, the goal of thisproposal isto abstract both client- andserver-side

    request andresponse interfacesin orderto promote interoperability between

    projects. If projectsimplement these interfaces, a reasonable level of

    compatibility may be assumedwhen adopting code from different libraries.

    It shouldbe notedthat the goal of thisproposal isnot to obsolete the current

    interfacesutilizedby existing PHP libraries. Thisproposal isaimedat

    interoperability between PHP packagesforthe purpose of describing HTTP

    messages.

    4. Scope

    4.1Goals

    Provide the interfacesneededfordescribing HTTP messages.

    Focuson practical applicationsandusability.

    Define the interfacesto model all elementsof the HTTP message andURI

    specifications.

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    6/22

    Ensure that the APIdoesnot impose arbitrary limitson HTTP messages.

    Forexample, some HTTP message bodiescan be too large to store in

    memory, so we must account forthis.

    Provide useful abstractionsboth forhandling incoming requestsfor

    server-side applicationsandforsending outgoing requestsin HTTP

    clients.

    4.2Non-Goals

    Thisproposal doesnot expect all HTTP client librariesorserver-side

    frameworksto change theirinterfacesto conform. It isstrictly meant for

    interoperability.

    While everyone'sperception of what isandisnot an implementation

    detail varies, thisproposal shouldnot impose implementation details. As

    RFCs7230, 7231, and3986do not force any particularimplementation,

    there will be a certain amount of invention neededto describe HTTP

    message interfacesin PHP.

    5. Design Decisions

    Message design

    The MessageInterface providesaccessorsforthe elementscommon to all

    HTTP messages, whetherthey are forrequestsorresponses. These elements

    include:

    HTTP protocol version (e.g., "1.0", "1.1")

    HTTP headers

    HTTP message body

    More specific interfacesare usedto describe requestsandresponses, and

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    7/22

    more specifically the context of each (client- vs. server-side). These divisions

    are partly inspiredby existing PHP usage, but also by otherlanguagessuch as

    Ruby'sRack, Python'sWSGI, Go'shttp package, Node'shttp module, etc.

    Why are there headermethodson messagesratherthan in a headerbag?

    The message itself isa containerforthe headers(aswell asthe other

    message properties). Howthese are representedinternally isan

    implementation detail, but uniform accessto headersisa responsibility of

    the message.

    Why are URIsrepresentedasobjects?

    URIsare values, with identity definedby the value, andthusshouldbe

    modeledasvalue objects.

    Additionally, URIscontain a variety of segmentswhich may be accessed

    many timesin a given request -- andwhich wouldrequire parsing the URIin

    orderto determine (e.g., via parse_url() ). Modeling URIsasvalue objects

    allowsparsing once only, andsimplifiesaccessto individual segments. It also

    providesconvenience in client applicationsby allowing usersto create new

    instancesof a base URIinstance with only the segmentsthat change (e.g.,

    updating the path only).

    Why doesthe request interface have methodsfordealing with therequest-target AND compose a URI?

    RFC 7230detailsthe request line ascontaining a "request-target". Of the four

    formsof request-target, only one isa URIcompliant with RFC 3986; the most

    common form usedisorigin-form, which representsthe URIwithout the

    scheme orauthority information. Moreover, since all formsare validfor

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    8/22

    purposesof requests, the proposal must accommodate each.

    RequestInterface thushasmethodsrelating to the request-target. By default,

    it will use the composedURIto present an origin-form request-target, and, in

    the absence of a URIinstance, return the string "/". Anothermethod,

    withRequestTarget() , allowsspecifying an instance with a specific request-

    target, allowing usersto create requeststhat use one of the othervalid

    request-target forms.

    The URIiskept asa discrete memberof the request fora variety of reasons.

    Forboth clientsandservers, knowledge of the absolute URIistypically

    required. In the case of clients, the URI, andspecifically the scheme andauthority details, isneededin orderto make the actual TCP connection. For

    server-side applications, the full URIisoften requiredin orderto validate the

    request orto route to an appropriate handler.

    Why value objects?

    The proposal modelsmessagesandURIsasvalue objects.

    Messagesare valueswhere the identity isthe aggregate of all partsof the

    message; a change to any aspect of the message isessentially a new

    message. Thisisthe very definition of a value object. The practice by which

    changesresult in a newinstance istermedimmutability, andisa feature

    designedto ensure the integrity of a given value.

    The proposal also recognizesthat most clientsandserver-side applications

    will needto be able to easily update message aspects, and, assuch, provides

    interface methodsthat will create newmessage instanceswith the updates.

    These are generally prefixedwith the verbiage with or without .

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    9/22

    Value objectsprovidesseveral benefitswhen modeling HTTP messages:

    Changesin URIstate cannot alterthe request composing the URIinstance.

    Changesin headerscannot alterthe message composing them.

    In essence, modeling HTTP messagesasvalue objectsensuresthe integrity of

    the message state, andpreventsthe needforbi-directional dependencies,

    which can often go out-of-sync orleadto debugging orperformance issues.

    ForHTTP clients, they allowconsumersto builda base request with data such

    asthe base URIandrequiredheaders, without needing to builda brandnew

    request orreset request state foreach message the client sends:

    $uri = new Uri('http://api.example.com');

    $baseRequest = new Request($uri, null, [

    'Authorization' => 'Bearer ' . $token,

    'Accept' => 'application/json',

    ]);;

    $request = $baseRequest->withUri($uri->withPath('/user'))->withMethod('GET'

    $response = $client->send($request);

    // get user id from $response

    $body = new StringStream(json_encode(['tasks' => [

    'Code',

    'Coffee',]]));;

    $request = $baseRequest

    ->withUri($uri->withPath('/tasks/user/' . $userId))

    ->withMethod('POST')

    ->withHeader('Content-Type', 'application/json')

    ->withBody($body);

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    10/22

    $response = $client->send($request)

    // No need to overwrite headers or body!

    $request = $baseRequest->withUri($uri->withPath('/tasks'))->withMethod('GE

    $response = $client->send($request);

    On the server-side, developerswill needto:

    Deserialize the request message body.

    Decrypt HTTP cookies.

    Write to the response.

    These operationscan be accomplishedwith value objectsaswell, with a

    numberof benefits:

    The original request state can be storedforretrieval by any consumer.

    A default response state can be createdwith default headersand/or

    message body.

    Most popularPHP frameworkshave fully mutable HTTP messagestoday. The

    main changesnecessary in consuming true value objectsare:

    Insteadof calling settermethodsorsetting public properties, mutator

    methodswill be called, andthe result assigned.

    Developersmust notify the application on a change in state.

    Asan example, in ZendFramework 2, insteadof the following:

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    11/22

    function (MvcEvent $e)

    {

    $response = $e->getResponse();

    $response->setHeaderLine('x-foo', 'bar');

    }

    one wouldnowwrite:

    function (MvcEvent $e)

    {

    $response = $e->getResponse();

    $e->setResponse(

    $response->withHeader('x-foo', 'bar')

    );

    }

    The above combinesassignment andnotification in a single call.

    Thispractice hasa side benefit of making explicit any changesto application

    state being made.

    Newinstancesvsreturning $this

    One observation made on the various with*() methodsisthat they can likely

    safely return $this; if the argument presentedwill not result in a change in

    the value. One rationale fordoing so isperformance (asthiswill not result in

    a cloning operation).

    The variousinterfaceshave been written with verbiage indicating that

    immutability MUST be preserved, but only indicate that "an instance" must

    be returnedcontaining the newstate. Since instancesthat represent the

    same value are consideredequal, returning $this isfunctionally equivalent,

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    12/22

    andthusallowed.

    Using streamsinsteadof X

    MessageInterface usesa body value that must implement StreamInterface .

    Thisdesign decision wasmade so that developerscan sendandreceive

    (and/orreceive andsend) HTTP messagesthat contain more data than can

    practically be storedin memory while still allowing the convenience of

    interacting with message bodiesasa string. While PHP providesa stream

    abstraction by way of stream wrappers, stream resourcescan be

    cumbersome to work with: stream resourcescan only be cast to a string

    using stream_get_contents() ormanually reading the remainderof a string.Adding custom behaviorto a stream asit isconsumedorpopulatedrequires

    registering a stream filter; however, stream filterscan only be addedto a

    stream afterthe filterisregisteredwith PHP (i.e., there isno stream filter

    autoloading mechanism).

    The use of a well- definedstream interface allowsforthe potential of flexible

    stream decoratorsthat can be addedto a request orresponse pre-flight to

    enable thingslike encryption, compression, ensuring that the numberof

    bytesdownloadedreflectsthe numberof bytesreportedin the Content-

    Length of a response, etc. Decorating streamsisa well-establishedpattern in

    the JavaandNodecommunitiesthat allowsforvery flexible streams.

    The majority of the StreamInterface APIisbasedon Python'sio module,

    which providesa practical andconsumable API. Insteadof implementing

    stream capabilitiesusing something like a WritableStreamInterface and

    ReadableStreamInterface , the capabilitiesof a stream are providedby

    methodslike isReadable() , isWritable() , etc. Thisapproach isusedby

    Python, C#, C++, Ruby, Node, andlikely others.

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    13/22

    What if Ijust want to return a file?

    In some cases, youmay want to return a file from the filesystem. The typical

    way to do thisin PHP isone of the following:

    readfile($filename);

    stream_copy_to_stream(fopen($filename, 'r'), fopen('php://output', 'w'));

    Note that the above omitssending appropriate Content-Type and Content-

    Length headers; the developerwouldneedto emit these priorto calling the

    above code.

    The equivalent using HTTP messageswouldbe to use a StreamInterface

    implementation that acceptsa filename and/orstream resource, andto

    provide thisto the response instance. A complete example, including setting

    appropriate headers:

    // where Stream is a concrete StreamInterface:

    $stream = new Stream($filename);

    $finfo = new finfo(FILEINFO_MIME);

    $response = $response

    ->withHeader('Content-Type', $finfo->file($filename))

    ->withHeader('Content-Length', (string) filesize($filename))

    ->withBody($stream);

    Emitting thisresponse will sendthe file to the client.

    What if Iwant to directly emit output?

    Directly emitting output (e.g. via echo , printf , orwriting to the

    php://output stream) isgenerally only advisable asa performance

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    14/22

    optimization orwhen emitting large data sets. If it needsto be done andyou

    still wish to work in an HTTP message paradigm, one approach wouldbe to

    use a callback-based StreamInterface implementation, perthisexample.

    Wrap any code emitting output directly in a callback, passthat to an

    appropriate StreamInterface implementation, andprovide it to the message

    body:

    $output = new CallbackStream(function () use ($request) {

    printf("The requested URI was: %s
    \n", $request->getUri());

    return '';

    });

    return (new Response())

    ->withHeader('Content-Type', 'text/html')

    ->withBody($output);

    What if Iwant to use an iteratorforcontent?

    Ruby'sRack implementation usesan iterator-basedapproach forserver-side

    response message bodies. Thiscan be emulatedusing an HTTP messageparadigm via an iterator-backed StreamInterface approach, asdetailedin the

    psr7examplesrepository.

    Why are streamsmutable?

    The StreamInterface APIincludesmethodssuch as write() which can

    change the message content -- which directly contradictshaving immutablemessages.

    The problem that arisesisdue to the fact that the interface isintendedto

    wrap a PHP stream orsimilar. A write operation therefore will proxy to writing

    to the stream. Even if we made StreamInterface immutable, once the stream

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    15/22

    hasbeen updated, any instance that wrapsthat stream will also be updated

    -- making immutability impossible to enforce.

    Ourrecommendation isthat implementationsuse read-only streamsfor

    server-side requestsandclient-side responses.

    Rationale forServerRequestInterface

    The RequestInterface and ResponseInterface have essentially 1:1correlations

    with the request andresponse messagesdescribedin RFC 7230. They provide

    interfacesforimplementing value objectsthat correspondto the specific

    HTTP message typesthey model.

    Forserver-side applicationsthere are otherconsiderationsforincoming

    requests:

    Accessto serverparameters(potentially derivedfrom the request, but

    also potentially the result of serverconfiguration, andgenerally

    representedvia the $_SERVER superglobal; these are part of the PHP

    ServerAPI(SAPI)).

    Accessto the query string arguments(usually encapsulatedin PHP via the

    $_GET superglobal).

    Accessto the parsedbody (i.e., data deserializedfrom the incoming

    request body; in PHP, thisistypically the result of POST requestsusing

    application/x-www-form-urlencoded content types, andencapsulatedin the

    $_POST superglobal, but fornon-POST, non-form-encodeddata, couldbean array oran object).

    Accessto uploadedfiles(encapsulatedin PHP via the $_FILES

    superglobal).

    Accessto cookie values(encapsulatedin PHP via the $_COOKIE

    superglobal).

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    16/22

    Accessto attributesderivedfrom the request (usually, but not limitedto,

    those matchedagainst the URL path).

    Uniform accessto these parametersincreasesthe viability of interoperability

    between frameworksandlibraries, asthey can nowassume that if a request

    implements ServerRequestInterface , they can get at these values. It also

    solvesproblemswithin the PHP language itself:

    Until 5.6.0, php://input wasread-once; assuch, instantiating multiple

    request instancesfrom multiple frameworks/librariescouldleadto

    inconsistent state, asthe first to access php://input wouldbe the only

    one to receive the data.

    Unit testing against superglobals(e.g., $_GET , $_FILES , etc.) isdifficult

    andtypically brittle. Encapsulating them inside the

    ServerRequestInterface implementation easestesting considerations.

    Why "parsedbody" in the ServerRequestInterface?

    Argumentswere made to use the terminology "BodyParams", andrequire the

    value to be an array, with the following rationale:

    Consistency with otherserver-side parameteraccess.

    $_POST isan array, andthe 80% use case wouldtarget that superglobal.

    A single type makesfora strong contract, simplifying usage.

    The main argument isthat if the body parametersare an array, developers

    have predictable accessto values:

    $foo = isset($request->getBodyParams()['foo'])

    ? $request->getBodyParams()['foo']

    : null;

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    17/22

    The argument forusing "parsedbody" wasmade by examining the domain. A

    message body can contain literally anything. While traditional web

    applicationsuse formsandsubmit data using POST, thisisa use case that is

    quickly being challengedin current web development trends, which are often

    APIcentric, andthususe alternate request methods(notably PUT and

    PATCH), aswell asnon-form-encodedcontent (generally JSONorXML) that

    canbe coercedto arraysin many cases, but in many casesalso cannotor

    shouldnot.

    If forcing the property representing the parsedbody to be only an array,

    developersthen needa sharedconvention about where to put the resultsof

    parsing the body. These might include:

    A special key underthe body parameters, such as __parsed__ .

    A special namedattribute, such as __body__ .

    The endresult isthat a developernowhasto look in multiple locations:

    $data = $request->getBodyParams();

    if (isset($data['__parsed__']) &&is_object($data['__parsed__'])) {

    $data = $data['__parsed__'];

    }

    // or:

    $data = $request->getBodyParams();

    if ($request->hasAttribute('__body__')) {

    $data = $request->getAttribute('__body__');

    }

    The solution presentedisto use the terminology "ParsedBody", which implies

    that the valuesare the resultsof parsing the message body. Thisalso means

    that the return value willbe ambiguous; however, because thisisan attribute

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    18/22

    of the domain, thisisalso expected. Assuch, usage will become:

    $data = $request->getParsedBody();

    if (! $data instanceof \stdClass) {

    // raise an exception!

    }

    // otherwise, we have what we expected

    Thisapproach removesthe limitationsof forcing an array, at the expense of

    ambiguity of return value. Considering that the othersuggestedsolutions

    pushing the parseddata into a special body parameterkey orinto an

    attribute also sufferfrom ambiguity, the proposedsolution issimplerasit

    doesnot require additionsto the interface specification. Ultimately, the

    ambiguity enablesthe flexibility requiredwhen representing the resultsof

    parsing the body.

    Why isno functionality includedforretrieving the "base path"?

    Many frameworksprovide the ability to get the "base path," usuallyconsideredthe path up to andincluding the front controller. Asan example, if

    the application isservedat http://example.com/b2b/index.php , andthe

    current URIusedto request it is http://example.com/b2b/index.php/customer

    /register , the functionality to retrieve the base path wouldreturn

    /b2b/index.php . Thisvalue can then be usedby routersto strip that path

    segment priorto attempting a match.

    Thisvalue isoften also then usedforURIgeneration within applications;

    parameterswill be passedto the router, which will generate the path, and

    prefix it with the base path in orderto return a fully-qualifiedURI. Othertools

    typically viewhelpers, template filters, ortemplate functions are used

    to resolve a path relative to the base path in orderto generate a URIfor

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    19/22

    linking to resourcessuch asstatic assets.

    On examination of several different implementations, we noticedthe

    following:

    The logic fordetermining the base path varieswidely between

    implementations. Asan example, compare the logic in ZF2to the logic in

    Symfony 2.

    Most implementationsappearto allowmanual injection of a base path to

    the routerand/orany facilitiesusedforURIgeneration.

    The primary use cases routing andURIgeneration typically are the

    only consumersof the functionality; developersusually do not needto beaware of the base path concept asotherobjectstake care of that detail

    forthem. Asexamples:

    A routerwill strip off the base path foryouduring routing; youdo not

    needto passthe modifiedpath to the router.

    Viewhelpers, template filters, etc. typically are injectedwith a base

    path priorto invocation. Sometimesthisismanually done, though

    more often it isthe result of framework wiring.

    All sourcesnecessary forcalculating the base path are already in the

    RequestInterface instance, via serverparametersandthe URIinstance.

    Ourstance isthat base path detection isframework and/orapplication

    specific, andthe resultsof detection can be easily injectedinto objectsthat

    needit, and/orcalculatedasneededusing utility functionsand/orclasses

    from the RequestInterface instance itself.

    Why doesgetUploadedFiles() return objectsinsteadof arrays?

    getUploadedFiles() returnsa tree of Psr\Http\Message\UploadedFileInterface

    instances. Thisisdone primarily to simplify specification: insteadof requiring

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    20/22

    paragraphsof implementation specification foran array, we specify an

    interface.

    Additionally, the data in an UploadedFileInterface isnormalizedto work in

    both SAPIandnon-SAPIenvironments. Thisallowscreation of processesto

    parse the message body manually andassign contentsto streamswithout

    first writing to the filesystem, while still allowing properhandling of file

    uploadsin SAPIenvironments.

    What about "special" headervalues?

    A numberof headervaluescontain unique representation requirements

    which can pose problemsboth forconsumption aswell asgeneration; in

    particular, cookiesandthe Accept header.

    Thisproposal doesnot provide any special treatment of any headertypes.

    The base MessageInterface providesmethodsforheaderretrieval andsetting,

    andall headervaluesare, in the end, string values.

    Developersare encouragedto write commodity librariesforinteracting with

    these headervalues, eitherforthe purposesof parsing orgeneration. Users

    may then consume these librarieswhen needing to interact with those

    values. Examplesof thispractice already exist in librariessuch as

    willdurand/Negotiationandaura/accept. So long asthe object has

    functionality forcasting the value to a string, these objectscan be usedto

    populate the headersof an HTTP message.

    6. People

    6.1Editor(s)

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    21/22

    MatthewWeierO'Phinney

    6.2Sponsors

    Paul M. Jones

    BeauSimensen (coordinator)

    6.3Contributors

    Michael Dowling

    Larry Garfield

    Evert Pot

    TobiasSchultze

    BernhardSchussek

    Anton Serdyuk

    Phil Sturgeon

    ChrisWilkinson

    Additional Info:

    PSR-7: HTTP message interfaces

    PSR-7: HTTP Message Meta Document

    Followuson Twitter Chat on IRC Channel Contribute via Github Join ourmailing list

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps

    22 19/06/2016 0

  • 7/25/2019 PSR-7_HTTP Message Meta Document - PHP-FIG

    22/22

    2016PHP Framework Interop Group. Site design by Jonathan Reinink.

    7: HTTP Message Meta Document - PHP-FIG http://www.php-fig.org/psr/ps


Top Related