Requests and responses

FloCMS\Core\Http\Request and Response are the HTTP classes shared by core and the API. Page controllers receive a request as $this->request; API handlers receive it as an argument. See validation for checking input.

Creating a request

use FloCMS\Core\Http\Request;

$request = Request::fromGlobals();

This captures $_GET, $_POST, $_SERVER, $_FILES, $_COOKIE and the raw body. fromGlobals($rawBody) lets you supply the body yourself. For API tests, prefer TestClient.

Input and JSON

Method Returns
input($key, $default = null) A value from the merged input
all() Query parameters, then form fields, then JSON, with later values replacing earlier ones
query() Only query parameters
queryValue($key, $default = null) One query parameter
rawBody() The unparsed body string
json() The decoded JSON array, or [] for empty, malformed or scalar JSON
jsonError() The decoding exception for malformed JSON, otherwise null

JSON participates in all() only for application/json or a content type ending in +json. Input is not validated or HTML-escaped automatically.

$title = $request->input('title', '');
$page = $request->queryValue('page', 1);

if ($request->jsonError() !== null) {
    // Reject the malformed body; json() alone would return [].
}

The API's JsonBodyMiddleware rejects malformed JSON before your handler runs. See middleware.

Method, URL and headers

Method Returns
method() Uppercase method, such as GET
isMethod('POST', 'PATCH') Whether the method matches any supplied method, ignoring case
isStateChanging() Whether it is POST, PUT, PATCH or DELETE
uri() The request URI, including its query string
path() Normalized path without the query; repeated slashes are collapsed
header($name, $default = null) A header, looked up without regard to case
headers() The header map, with lowercase keys
contentType() Lowercase media type without parameters such as charset
acceptsJson() Whether Accept contains application/json or +json
server($key, $default = null) A value from the captured server array
bearerToken() A Bearer token from Authorization or X-FloCMS-Authorization, otherwise null

acceptsJson() is a simple media-type check, not full HTTP content negotiation. bearerToken() extracts a credential; authenticators verify it. See API authentication.

Files and cookies

$file = $request->file('attachment');   // $_FILES entry, or null
$files = $request->files();
$theme = $request->cookie('theme', 'light');
$cookies = $request->cookies();

The request is a snapshot. Later changes made by Cookie::set() do not update this request's captured cookies. See cookies to write them and uploads to process files.

Route parameters and attributes

API route parameters and middleware attributes are separate from input:

$id = $request->route('id');
$params = $request->routeParams();
$identity = $request->attribute('identity');

route($name, $default = null) returns a string or null; attribute($name, $default = null) returns the stored value. attributes() returns all attributes.

withAttribute($name, $value) and withRouteParams($params) return a cloned request. Pass the returned object onward:

$nextRequest = $request->withAttribute('client_version', '2');
// $request is unchanged; the middleware's next handler receives $nextRequest.

Page routing also exposes positional parameters through the page controller's $params; those are not API named route parameters. See routing.

Creating responses

use FloCMS\Core\Http\Response;

$response = Response::json(['status' => 'ok']);
$response->header('X-Example', 'yes');
Factory Default status and content type
make($body = '', $status = 200) 200; no content type added
html($html, $status = 200) 200; text/html; charset=utf-8
text($text, $status = 200) 200; text/plain; charset=utf-8
json($data, $status = 200) 200; application/json; charset=utf-8
noContent($status = 204) 204; empty body

Response::json() encodes exactly the data you supply. It does not add the API's success envelope. For that envelope use FloCMS\Api\ResponseFactory or the API controller helpers.

use FloCMS\Api\ResponseFactory;

$plain = Response::json(['status' => 'ok']);
// {"status":"ok"}

$api = ResponseFactory::success(['status' => 'ok']);
// {"success":true,"data":{"status":"ok"}}

Headers and sending

Method Does
header($name, $value) Sets/replaces a header, case-insensitively, and returns this response
appendHeader($name, $value) Appends to the header using a comma separator
status(), body(), headers() Inspect the response
withoutBody() Returns a clone with an empty body
send() Sends status, headers and body; it does not exit

Header setters mutate the response. Header names are validated and values cannot contain line breaks. appendHeader() is for comma-separated headers, not multiple Set-Cookie values; use the cookie API for cookies.

send() omits the body for status 204 or 304. Invalid status codes and JSON encoding failures throw RuntimeException.

API handlers return a response and the kernel sends it. The page runtime renders views; it does not automatically send an action's returned Response. To output a response from a page action, send it and stop before view rendering:

public function status(): void
{
    \FloCMS\Core\Http\Response::text('ok')->send();
    exit;
}
Esc