-
Notifications
You must be signed in to change notification settings - Fork 2
Request
Pair\Api\Request is the HTTP wrapper used by Pair API controllers.
It covers:
- method and header access
- lazy JSON body parsing
- query parameter access
- lightweight validation rules
- bearer token and idempotency-key extraction
- trusted-proxy-aware client IP resolution
Use these when the controller needs to inspect the request shape quickly.
$method = $this->request->method(); // GET, POST, PUT...
$auth = $this->request->header('Authorization');
$contentType = $this->request->header('Content-Type');
$page = $this->request->query('page', 1);
$allQuery = $this->request->query();all() merges $_GET and the parsed JSON body, with JSON values taking precedence when the same key exists in both places:
// GET /api/users?page=2 with JSON body {"status":"active"}
$all = $this->request->all();
// ['page' => '2', 'status' => 'active']rawBody() reads php://input lazily and caches it.
json() parses the request body as JSON and returns either the whole associative array or a single key:
$body = $this->request->json();
$email = $this->request->json('email');isJson() checks whether the content type includes application/json.
if (!$this->request->isJson()) {
\Pair\Api\ApiResponse::error('UNSUPPORTED_MEDIA_TYPE', [
'expected' => 'application/json',
]);
}Practical note: the current implementation expects the decoded JSON body to be an array. Invalid JSON, empty bodies, or scalar JSON payloads effectively behave like null.
Supported rules:
requiredstringintnumericemailboolmin:Nmax:N
Example:
$data = $this->request->validate([
'email' => 'required|email|max:120',
'age' => 'int|min:18',
'newsletter' => 'bool',
]);Current behavior:
-
validate()returns only validated keys - missing optional fields are skipped
- on error, Pair responds immediately with
INVALID_FIELDS - validated values are not cast automatically
That last point matters:
-
intaccepts digit strings, but you should still cast to(int)yourself -
boolacceptstrue,false,1,0,'1','0','true','false', but it does not cast the result to a PHP boolean for you
Required-only shortcut:
$data = $this->request->requireFields(['email', 'password']);bearerToken() extracts Authorization: Bearer ... when present.
idempotencyKey() supports both:
Idempotency-KeyX-Idempotency-Key
isReplayRequest() returns true when X-Pair-Replay is 1 or true.
$token = $this->request->bearerToken();
$key = $this->request->idempotencyKey();
if (!$token) {
\Pair\Api\ApiResponse::error('AUTH_TOKEN_MISSING');
}Replay-aware example:
if ($this->request->isReplayRequest()) {
// optional branch for offline queue or retried mobile requests
}ip() returns the effective client IP.
Current behavior:
- uses
REMOTE_ADDRby default - trusts
ForwardedandX-Forwarded-Foronly whenREMOTE_ADDRbelongs toPAIR_TRUSTED_PROXIES - supports exact proxy IPs and CIDR ranges in
PAIR_TRUSTED_PROXIES - prefers the standardized
Forwardedheader when available
Example .env:
PAIR_TRUSTED_PROXIES=127.0.0.1,10.0.0.0/8,192.168.0.0/16Example:
$ip = $this->request->ip();
$limiterKey = 'throttle:login:' . $ip;-
rawBody()andjson()are lazy and cached. -
header()handles special server variables such asContent-TypeandContent-Length. -
all()is convenient, but remember that JSON overrides same-named query parameters.
- Assuming JSON is always present on
POST,PUT, orPATCH. - Forgetting that
all()lets JSON override same-named query keys. - Treating
intorboolvalidation as automatic type casting. - Trusting forwarded headers without configuring
PAIR_TRUSTED_PROXIES.
See also: API, ApiResponse, Idempotency, ThrottleMiddleware.