> For the complete documentation index, see [llms.txt](https://quantumphp.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://quantumphp.gitbook.io/docs/packages/http/request.md).

# Request

## Purpose

`Quantum\Http\Request` is Quantum's mutable snapshot of the current HTTP request.

It combines server-derived metadata with helper methods for:

* request body values
* headers
* files
* query strings and URL segments
* matched-route metadata
* synthetic internal requests for testing-style flows

## Method and URL state

The request object stores:

* method
* protocol
* host
* port
* URI
* raw query string

`setMethod()` validates against `Request::METHODS` and throws `HttpException` for unsupported methods.

Supported methods are currently limited to:

* `GET`
* `POST`
* `PUT`
* `PATCH`
* `DELETE`

`isMethod()` compares case-insensitively, so callers can safely check `isMethod('post')` even if the stored value is uppercase.

## Base URL and current URL

`getBaseUrl(bool $withModulePrefix = false)` first reads `config()->get('app.base_url')`.

If that config value exists, it returns that base URL and optionally appends the matched route prefix.

If the config value is empty, it falls back to a host prefix built from protocol, host, and port.

Port handling is conservative:

* port `80` is omitted for `http`
* port `443` is omitted for `https`
* any other port is included

`getCurrentUrl()` always uses the current protocol/host/port snapshot plus the current URI and raw query string.

## Body parameter access

The request body store lives in an internal array and is accessed with:

* `has($key)`
* `get($key, $default = null, $raw = false)`
* `set($key, $value)`
* `all()`
* `delete($key)`

### Sanitization contract

`get()` strips HTML tags by default.

* scalar values are passed through `strip_tags()`
* array values are transformed with `array_map('strip_tags', $value)`
* raw values are returned unchanged only when `$raw = true`

That means `get()` is not a pure retrieval API. It performs output-oriented sanitization unless you opt out.

### Reserved key guard

`set()` rejects the reserved key stored in `Quantum\App\Enums\ReservedKeys::RENDERED_VIEW`.

Trying to write that key raises `InvalidArgumentException`.

### `all()` behavior

`all()` returns merged request parameters plus uploaded files.

If a key exists in both payload data and files, the later merge from the files array wins.

## Input parsing and precedence

`setRequestParams()` rebuilds the request payload by merging five sources in order:

1. `getParams()` from `$_GET`
2. `postParams()` from `$_POST`
3. `jsonPayloadParams()`
4. `urlEncodedParams()`
5. explicit parsed params passed into `setRequestParams()`

This makes raw multipart parameters the highest-precedence source during normal bootstrap.

### JSON payload parsing

JSON parsing runs only when both conditions match:

* method is `PUT`, `PATCH`, or `POST`
* normalized content type is exactly `application/json`

Invalid JSON quietly becomes an empty array because `json_decode(..., true) ?: []` is used.

### URL-encoded raw body parsing

URL-encoded raw body parsing uses the same method gate and requires content type `application/x-www-form-urlencoded`.

The implementation applies `urldecode()` before `parse_str()`. Callers get the parsed array only; there is no separate raw representation.

### Multipart raw parsing

Raw multipart parsing runs only when both conditions match:

* method is `PUT`, `PATCH`, or `POST`
* normalized content type is exactly `multipart/form-data`

The parser extracts the multipart boundary from `server()->contentType()` and then processes each block as either:

* a normal parameter
* a file part
* an octet-stream field

Notable details from the parser:

* fields named like `tags[]` are accumulated into arrays
* file parts are written to temporary files under the system temp directory
* those temp files are registered for removal with `register_shutdown_function()`
* file parts with empty content are skipped
* array-like file names such as `photos[]` or `photos[cover]` become nested file collections

## Uploaded files

`setUploadedFiles()` merges normalized `$_FILES` with parsed raw multipart files.

`handleFiles()` converts each entry into `Quantum\Storage\UploadedFile` objects.

It supports:

* single uploads -> one `UploadedFile`
* multi-file top-level arrays -> `array<UploadedFile>`

`hasFile($key)` returns `true` only when the key exists and every uploaded file under that key has `UPLOAD_ERR_OK`.

`getFile($key)` throws `FileUploadException::fileNotFound(...)` when that check fails.

## Header access

Request headers are stored with lowercase keys, but lookup is tolerant.

`hasHeader()` and `getHeader()` normalize the requested key into both hyphen and underscore forms, so these lookups are treated as equivalent:

* `Content-Type`
* `content-type`
* `CONTENT_TYPE`

### Authorization helpers

`getAuthorizationBearer()` returns the token only when the `Authorization` header matches `Bearer <token>`.

`getBasicAuthCredentials()` prefers server variables `PHP_AUTH_USER` and `PHP_AUTH_PW`. If those are missing, it falls back to decoding a `Basic <base64>` authorization header.

Invalid or non-decodable Basic auth values return `null`.

### AJAX and referrer helpers

`isAjax()` returns `true` when either of these is true:

* header `X-REQUESTED-WITH` exists
* `server()->ajax()` returns true

`getReferrer()` simply proxies `server()->referrer()`.

## Query string helpers

The query helpers work on the raw stored query string, not on a decoded map.

`getQueryParam($key)`:

* splits on `&`
* splits each pair on `=`
* returns the first matching raw value
* does not URL-decode the value

`setQueryParam($key, $value)` always appends a new `key=value` pair.

It does not replace existing keys and does not encode the value.

## URI segments

`getUri()` stores the request URI without a leading slash.

`getAllSegments()` parses the URI path, trims outer slashes, and prepends a sentinel element:

```php
['zero_segment', ...actualSegments]
```

That means segment access is effectively 1-based for real path parts.

`getSegment(1)` returns the first real path segment.

If the URI is `null`, `getAllSegments()` returns `['zero_segment']`.

## CSRF token lookup

`getCsrfToken()` checks the request payload first and then the header `X-<TOKEN_KEY>`.

The first match wins.

## Route metadata access

The request can hold a `Quantum\Router\MatchedRoute` instance.

From that object, the package exposes read helpers for:

* current middlewares
* current module
* current controller
* current action
* route closure callback
* original route pattern
* compiled route pattern
* route parameters
* route cache settings
* route name
* route prefix

If no route has been set, these helpers return `null` or `[]` depending on the method.

### Route collection lookups

`findRouteByName($name, $module)` and `routeGroupExists($name, $module)` only work when `RouteCollection::class` has already been registered in DI.

If not, they return `null` or `false` instead of constructing anything.

Both lookups are case-insensitive for the requested name and module.

### Module namespace helper

`getModuleBaseNamespace()` hardcodes two environments:

* testing -> `Quantum\\Tests\\_root\\modules`
* everything else -> `Modules`

## Internal request creation

`create($method, $url, $params = [], $headers = [], $files = [])` rewrites the shared server state and rebuilds the request object from it.

It is intended for internal or testing-style request simulation.

The method performs these steps:

1. parses the target URL
2. flushes the shared server object
3. writes request method, URI, scheme, host, port, and query into that server object
4. infers content type from the presence of params or files
5. writes custom headers as `HTTP_*` server entries
6. flushes the request object's stored headers/body/files/URL pieces
7. repopulates the request from the rewritten server state
8. optionally overwrites params and files with the explicit arrays passed in

Content-type inference is simple:

* files present -> `multipart/form-data`
* params present -> `application/x-www-form-urlencoded`
* neither -> `text/html`

## Flush behavior

`flush()` clears:

* headers
* request payload
* files
* protocol
* host
* port
* URI
* query string

It is not a full reset helper. It does not clear the matched route property directly.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://quantumphp.gitbook.io/docs/packages/http/request.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
