Request Handling#

This guide shows how to read input (query, JSON, form, files), headers, cookies, route params, and attributes from Infocyph\Webrick\Request\Request. It also covers method overrides and locale/negotiation attributes.


Getting a Request instance#

Handlers receive it as the first parameter when you type-hint it:

use Infocyph\Webrick\Request\Request;
use Infocyph\Webrick\Response\Response;

Route::post('/echo', function (Request $r) {
    return Response::json([
        'method'  => $r->getMethod(),
        'query'   => $r->query(),
        'input'   => $r->all(),
        'headers' => $r->getHeaders(),
    ]);
});

You can mix typed route params and a Request argument in any order.


HTTP method & URI#

$r->getMethod();                 // "GET", "POST", ...
$r->getUri();                    // PSR-7 style URI or a Router-native Uri object
$r->getPath();                   // "/users/42"
$r->getQueryParams();            // ['page' => '2']

Method override (forms)#

If you enabled NormalizeMethodMiddleware, HTML forms can send POST with _method=PUT|PATCH|DELETE (in body or query). The effective method becomes the override.


Query string & input body#

Query#

$r->query('page', 1);            // 1 if missing
$r->query();                     // all query params

Form-URL-Encoded or Multipart#

$r->input('email');              // from body (form fields)
$r->all();                       // merged input (query + body)
$r->only(['email','name']);      // convenience filters (if provided)
$r->except(['_token']);          // exclude keys

JSON#

If Content-Type: application/json, the request parses JSON and exposes it via the same helpers:

$r->json();                      // full decoded JSON (array|scalar|null on invalid/empty)
$r->json('user.id');             // dot-access helper if available, else null

If payload can be large, prefer reading only the keys you need.


Files (multipart)#

$files = $r->files();            // array-like, keyed by input name
$avatar = $r->file('avatar');    // UploadedFile-like (tmp path, size, error, clientName, clientType)

Validate size and extension at upload time; store outside webroot and generate your own filenames.


Headers & server params#

$r->getHeaders();                // ['content-type'=>['application/json'], ...]
$r->getHeader('accept');         // ["application/json"]
$r->getHeaderLine('accept');     // "application/json"
$r->server('REMOTE_ADDR');       // "203.0.113.10"

Common helpers#

  • Client IP (behind trusted proxies): ensure your proxy settings are correct before trusting X-Forwarded-For.

  • User-Agent: $r->getHeaderLine('user-agent')


Cookies#

If CookieEncryptionMiddleware is enabled, decrypted values appear in the request:

$r->getCookieParams();           // all cookies (decrypted when enabled)
$r->cookie('session_id');        // value or null

For security, mark auth cookies HttpOnly; SameSite=...; Secure.


Route parameters#

Values captured from the path are injected into your handler by name and also available on the request:

Route::get('/users/{id:int}', function (Request $r, int $id) {
    // Both are equivalent:
    $idA = $id;
    $idB = (int)$r->param('id');
    return Response::json(['idA'=>$idA,'idB'=>$idB]);
});

Attributes (context passed by middleware)#

Middleware may attach contextual data to the Request:

$r->getAttributes();             // all attributes
$r->getAttribute('locale');      // e.g., "en" from negotiation middleware
$r->getAttribute('signed');      // e.g., true if VerifySignedUrl passed

You can also set your own attributes in custom middleware to pass state down the pipeline.


Content negotiation helpers#

If NegotiationMiddleware is active, you can read negotiation decisions:

$r->getAttribute('locale');      // resolved locale
$r->getHeaderLine('accept');     // client's Accept header

Then produce a response via convenience helpers:

Response::auto($r, ['data' => 'value']);   // chooses JSON/text/XML sanely

Reading the raw body / streams#

For advanced cases (e.g., HMAC verification or NDJSON streams):

$raw = $r->getBody();            // raw string or stream contents
$stream = $r->getBodyStream();   // stream resource if available

Avoid reading the entire body into memory for very large uploads; stream/pipe instead when possible.


CSRF & idempotency tips#

  • CSRF: for state-changing routes from browsers, enforce a CSRF token (pair with SameSite cookies or use double-submit).

  • Idempotency: consider an Idempotency-Key header on POST APIs that can be retried; store and dedupe server-side.


Examples#

Echo JSON with validation#

Route::post('/api/user', function (Request $r) {
    $user = $r->json();
    if (!isset($user['email'])) {
        return Response::json(['error'=>'email required'], 422);
    }
    // ... create user
    return Response::json(['ok'=>true], 201);
});

File upload#

Route::post('/upload', function (Request $r) {
    $file = $r->file('avatar');
    if (!$file || $file->getError()) {
        return Response::json(['error'=>'invalid upload'], 400);
    }
    // validate size/mime; move to storage
    // move_uploaded_file($file->getTmpName(), $destination);
    return Response::json(['ok'=>true]);
});

Checklist#

  • Trust proxy headers only if you control the proxy chain

  • Validate and sanitize input; never trust Content-Type blindly

  • Use method override only when necessary, via NormalizeMethodMiddleware

  • Keep large bodies streaming; avoid buffering unbounded payloads

  • Treat cookies as untrusted input unless you encrypted & signed them