-
Notifications
You must be signed in to change notification settings - Fork 0
Server Request
InitPHP\HTTP\Message\ServerRequest is the PSR-7 server-side request: the one your application receives. On top of Request it carries the server params, cookies, query string, parsed body, uploaded files and a free-form attribute bag.
It implements Psr\Http\Message\ServerRequestInterface.
use InitPHP\HTTP\Message\ServerRequest;$request = ServerRequest::createFromGlobals();One line replaces the ten-line new ServerRequest(...) recipe. The factory:
- Reads
$_SERVER,$_GET,$_POST,$_COOKIE,$_FILESas defaults. - Computes the URI from
HTTPS/HTTP_HOST/SERVER_NAME/SERVER_PORT/REQUEST_URI. - Collects headers via
apache_request_headers()when available, or falls back to walking$_SERVERforHTTP_*andCONTENT_*keys (so nginx + php-fpm and FrankenPHP work). - Stages the request body on
php://temp(large bodies spill to disk, not memory). - Parses the body according to
Content-Typeand stores the result inparsedBody:-
application/json→json_decode(..., true)(if the decoded value is an array; otherwisenull). -
application/x-www-form-urlencoded→$_POSTif populated, elseparse_str(...). -
multipart/form-data→$_POST(already populated by PHP). - Anything else →
parsedBodyleft asnull.
-
- Normalises
$_FILESinto a tree ofUploadedFileInterfaceinstances vianormalizeFiles(), including arbitrarily nested input names (file[parent][child][…]).
Every call returns a fresh instance. There is no static caching. This is what makes the factory safe under long-running PHP runtimes — Swoole, RoadRunner, Octane, FrankenPHP — where a single process serves many requests:
$a = ServerRequest::createFromGlobals(
['REQUEST_METHOD' => 'GET', 'REQUEST_URI' => '/one', 'HTTP_HOST' => 'a.test'],
[], [], [], []
);
$b = ServerRequest::createFromGlobals(
['REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/two', 'HTTP_HOST' => 'b.test'],
[], [], [], []
);
$a === $b; // false — fresh instances
$a->getMethod(); // "GET"
$b->getMethod(); // "POST"v2 → v3 note: The legacy
Request::createFromGlobals()cached its result in a static property and reused it forever. That broke under any non-FPM runtime. The new factory is onServerRequest, notRequest, and is stateless. See Migration Guide.
Pass arrays explicitly to drive the factory without touching the real superglobals:
$request = ServerRequest::createFromGlobals(
['REQUEST_METHOD' => 'POST', 'REQUEST_URI' => '/cart', 'HTTP_HOST' => 'shop.test',
'CONTENT_TYPE' => 'application/json'],
[], // $_GET
[], // $_POST (unused for JSON)
[], // $_COOKIE
[] // $_FILES
);Test note: the JSON branch reads php://input for the body — under PHPUnit that's empty, so parsedBody will be null for JSON unless you provide the body via another route. Use $request->withParsedBody([...]) in tests.
$request = new ServerRequest(
'POST', // method
'/checkout', // URI
['Content-Type' => 'application/json'], // headers
'{"sku":"X-1"}', // body
'1.1', // version
$_SERVER // server params
);
$request = $request
->withCookieParams($_COOKIE)
->withQueryParams($_GET)
->withParsedBody(['sku' => 'X-1'])
->withUploadedFiles($request->normalizeFiles($_FILES))
->withAttribute('route', '/checkout');ServerRequest exposes every PSR-7 Request accessor (see Request) plus:
$request->getServerParams(); // array — the snapshot from $_SERVER
$request->getCookieParams(); // array — the snapshot from $_COOKIE
$request->getQueryParams(); // array — the snapshot from $_GET
$request->getParsedBody(); // null|array|object — Content-Type-driven
$request->getUploadedFiles(); // array<string, UploadedFileInterface|array>
$request->getAttributes(); // array — middleware-set state
$request->getAttribute('name'); // value or null
$request->getAttribute('name', $default);$updated = $request
->withCookieParams(['session' => 'abc'])
->withQueryParams(['q' => 'phpunit'])
->withParsedBody(['sku' => 'X-1'])
->withUploadedFiles($files)
->withAttribute('user', $user)
->withoutAttribute('temp');withParsedBody() accepts array, object, or null. Anything else raises InvalidArgumentException.
The normalizeFiles() instance method converts PHP's $_FILES shape (or a pre-built tree of UploadedFileInterfaces) into a normalised tree. It supports:
- The single-file shape:
['avatar' => ['tmp_name' => ..., 'size' => ...]]. - The simple-array shape (
<input type="file" name="docs[]" multiple>). - Arbitrarily nested names (
<input name="docs[brief]">,<input name="docs[exhibits][a]">, ...). - Pre-built
UploadedFileInterfaceinstances mixed in anywhere in the tree.
See UploadedFile for the moving / streaming / error handling surface.
Attributes are the place middleware stash decoded JWT claims, matched route parameters, DI handles, audit IDs:
$request = $request->withAttribute('user', $authenticatedUser);
$user = $request->getAttribute('user'); // value or null
$user = $request->getAttribute('user', $guest); // value or fallback
$request = $request->withoutAttribute('user');getAttributes() returns the entire bag as an associative array.
All the predicates from RequestTrait (isGet, isPost, isMethod(...), ...) are available; see Request.
- Recipe — File Upload for the receiving / moving / nested-name flow.
-
Recipe — Proxying Requests for forwarding an incoming
ServerRequestto an upstream service.
initphp/http · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
PSR-7 Messages
PSR-17 Factories
PSR-18 Client
Emitter (SAPI)
Static Facades
Recipes
Reference
Migration & Help