The Request Object
The Request Object
The Hazaar\Application\Request object is a central component in the Hazaar Framework that encapsulates all the details of an incoming HTTP request. It serves as the primary interface for accessing client input, including query parameters, form data, JSON payloads, and HTTP headers.
By automatically parsing and normalizing request data, the Request object simplifies the task of handling different types of requests, whether they are standard page loads, AJAX calls, or API interactions. It acts as a container for the state of the current request, ensuring that controllers and middleware have consistent access to the information they need to process the user's intent.
The request object is accessible within your controllers via $this->request and is instantiated automatically by the application during the bootstrap process.
Key capabilities include:
- Input Retrieval: Unified access to data from
$_GET,$_POST, and raw request bodies. - Content Parsing: Automatic decoding of JSON payloads into usable arrays.
- Header Access: Simple methods to retrieve and inspect HTTP headers.
- Method Detection: Helper methods to check the HTTP verb (GET, POST, PUT, DELETE, etc.).
- Context Awareness: Methods to detect AJAX requests, mobile devices, and client IP addresses.
- Data Passing: A mechanism to store and retrieve attributes, facilitating data sharing between middleware and controllers.
For a complete list of available methods and properties, please refer to the Request API documentation.
Request Methods
The request object provides the following methods to determine the request method:
- isGet() - Returns true if the request uses the
GETmethod. - isPut() - Returns true if the request uses the
PUTmethod. - isPost() - Returns true if the request uses the
POSTmethod. - isDelete() - Returns true if the request uses the
DELETEmethod. - getMethod() - Returns the name of the request method for this request.
Tips
Hazaar\Application\Request::getMethod() is available in CLI requests as well, but will always be GET.
public function action(): Response
{
if($this->request->isPOST()){
// Store the update and return status
}elseif($this->request->isGET()){
// Return the product
}
return BadRequest;
}Example
In this example our controller has a get method that returns a product formatted as JSON. The URL would be:
/api/v1/product/get/1234This URL loads Application\Controller\Product and executes its list method. The corresponding controller is located in application/controllers/api/v1/product.php:
namespace App\Controllers\Api\V1;
use Hazaar\Controller\Basic;
use Hazaar\Controller\Response;
use Hazaar\Controller\Response\Json;
use Hazaar\Controller\Response\HTTP\BadRequest;
use Hazaar\DBI\Adapter;
class Product extends Basic {
public function init(): void
{
// Initialization code
}
public function get(int $productId): Response
{
if(!$this->request->isGET()){
return new BadRequest;
}
$db = Adapter::create();
return new Json($db->table('product')->find(['id' => $productId]));
}
}Remote IP Address
The request object provides the getRemoteAddr() method to determine the remote IP address of the client making the request.
getRemoteAddr()- Returns the remote IP address.
public function action(): Response
{
$ip = $this->request->getRemoteAddr();
return new Json(['ip' => $ip]);
}Behind a Reverse Proxy
By default getRemoteAddr() returns $_SERVER['REMOTE_ADDR'] and ignores forwarding headers such as X-Forwarded-For, because any client can set them. If your app sits behind a load balancer, CDN or other reverse proxy, list the proxies you trust in app.trustedProxies:
'app' => [
'trustedProxies' => ['10.0.0.0/8', '172.16.0.0/12', '2001:db8::/32'],
// or as a comma-separated string, e.g. injected from an environment variable:
// 'trustedProxies' => '10.0.0.0/8,172.16.0.0/12',
'trustedProxyHeader' => 'X-Forwarded-For', // or 'Forwarded' (RFC 7239)
],Forwarding headers are only read when REMOTE_ADDR is in that list, and only the header named by trustedProxyHeader. The chain is walked right to left, skipping trusted proxies, and the first address that isn't trusted is returned as the client IP. If every hop is trusted, the leftmost is returned. An entry that isn't a valid IP stops the walk.
For example, with REMOTE_ADDR set to a load balancer at 10.0.0.5 and X-Forwarded-For: 6.6.6.6, 198.51.100.7:
- If the load balancer's subnet and the CDN edge
198.51.100.7are both trusted, the client IP is6.6.6.6. - If only the load balancer's subnet is trusted, the client IP is
198.51.100.7, because nothing past an untrusted hop can be verified.
For Cloudflare, trust its published edge ranges (https://www.cloudflare.com/ips-v4/ and https://www.cloudflare.com/ips-v6/). They change occasionally, so re-sync them from time to time.
The same trustedProxies list controls whether generated URLs use the X-Forwarded-Scheme, X-Forwarded-Host and X-Forwarded-Port headers. From an untrusted peer they're ignored, and from a trusted proxy each is validated (http/https, a valid hostname or IP, a port from 1 to 65535) before it's used.
For code that runs without an application config, such as tests or CLI tools, set the list directly with Request::setTrustedProxies(['10.0.0.0/8'], 'X-Forwarded-For'). Pass null to go back to the config value.
Tips
You can also do this at the web server. nginx's real_ip module (set_real_ip_from, real_ip_header X-Forwarded-For, real_ip_recursive on) rewrites REMOTE_ADDR before PHP sees the request, so getRemoteAddr() needs no trustedProxies config. Generated URLs still need trustedProxies to use the forwarded scheme, host and port.
Warning
By default Traefik replaces an incoming X-Forwarded-For instead of appending to it, unless forwardedHeaders.trustedIPs is set on the entrypoint. In that case list only Traefik's own address in trustedProxies.
Request Attributes
Request attributes are a mechanism to pass data between middleware and controllers, or between different middleware components. Attributes are stored on the Request object and persist for the duration of the request. This is useful for things like passing an authenticated user object or other data that is derived from the request.
setAttribute(string $key, mixed $value)- Sets a request attribute.getAttribute(string $key)- Retrieves a request attribute. Returnsnullif the attribute does not exist.
Setting Attributes
Attributes are typically set in middleware.
public function handle(Request $request, callable $next, mixed ...$args): Response
{
$request->setAttribute('key', 'value');
return $next($request);
}Getting Attributes
Attributes can be retrieved in controllers or subsequent middleware.
public function index(): Response
{
$value = $this->request->getAttribute('key') ?? 'default_value';
return new Json(['value' => $value]);
}