From redaxo-core
Builds HTTP/AJAX endpoints in REDAXO using rex_api_function for custom addons, including lib/class setup, published flag for frontend access, JSON responses, CORS headers, and rex-api-call URLs.
npx claudepluginhub friendsofredaxo/claude-marketplace --plugin redaxo-coreThis skill uses the workspace's default tool permissions.
`rex_api_function` is the built-in REDAXO mechanism for HTTP/AJAX endpoints from your own addon. Each endpoint is a class under `lib/` that extends `rex_api_function`. URL: `/index.php?rex-api-call=<class_suffix>`.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Guides code writing, review, and refactoring with Karpathy-inspired rules to avoid overcomplication, ensure simplicity, surgical changes, and verifiable success criteria.
Executes ctx7 CLI to fetch up-to-date library documentation, manage AI coding skills (install/search/generate/remove/suggest), and configure Context7 MCP. Useful for current API refs, skill handling, or agent setup.
Share bugs, ideas, or general feedback.
rex_api_function Endpointsrex_api_function is the built-in REDAXO mechanism for HTTP/AJAX endpoints from your own addon. Each endpoint is a class under lib/ that extends rex_api_function. URL: /index.php?rex-api-call=<class_suffix>.
This is not the same as the FriendsOfRedaxo/api addon (which is a full REST framework with route table, OpenAPI, etc.). rex_api_function is the lower-level core feature — perfect for one-off AJAX endpoints in a single addon.
<?php
// lib/api/save_item.php
class rex_api_my_addon_save_item extends rex_api_function
{
protected $published = true; // true = callable from frontend; false = backend only
public function execute()
{
// For JSON request bodies:
$input = json_decode(file_get_contents('php://input'), true);
if (!is_array($input)) {
rex_response::cleanOutputBuffers();
rex_response::setStatus(400);
rex_response::sendJson(['error' => 'Invalid JSON']);
exit;
}
// ...do work...
$result = ['id' => 42, 'saved' => true];
rex_response::cleanOutputBuffers();
rex_response::setStatus(200);
rex_response::sendJson(['data' => $result]);
exit;
}
}
lib/ directory of your addon (autoloaded by REDAXO)rex_api_ — without this, REDAXO doesn't dispatch to it$published flag:
true – endpoint reachable from frontend (no login required)false (default) – only callable when a backend user is logged inexit after sendJson() – REDAXO appends HTML otherwiseGET/POST /index.php?rex-api-call=my_addon_save_item
The URL suffix matches the part of the class name after rex_api_. So rex_api_my_addon_save_item → ?rex-api-call=my_addon_save_item.
When the endpoint is called from a different origin (e.g. an embedded widget on a third-party site), set CORS headers before any output:
public function execute()
{
rex_response::cleanOutputBuffers();
// CORS preflight + actual response headers
header('Access-Control-Allow-Origin: ' . ($_SERVER['HTTP_ORIGIN'] ?? '*'));
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
rex_response::setStatus(204);
exit;
}
// ...handle the actual request...
}
For tighter security, allowlist origins:
$allowed = ['https://partner1.com', 'https://partner2.com'];
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
if (in_array($origin, $allowed, true)) {
header('Access-Control-Allow-Origin: ' . $origin);
}
| Source | Code | Notes |
|---|---|---|
| Query string | rex_request::get('id', 'int', 0) | Type-coerced |
| Form body | rex_request::post('name', 'string', '') | Type-coerced |
| JSON body | json_decode(file_get_contents('php://input'), true) | Validate before use |
| Header | $_SERVER['HTTP_AUTHORIZATION'] ?? '' | Apache may strip — see below |
rex_request::get() / rex_request::post() give you type safety for free — prefer them over reading $_GET/$_POST directly.
AuthorizationIf your endpoint reads a Bearer token from the Authorization header and Apache strips it, add to .htaccess:
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
$published = false (or omitting it) and wondering why frontend AJAX gets 403 – set it to true for frontend endpoints.exit after sendJson() – the response gets the JSON, then a blob of REDAXO's normal HTML appended. Browsers parse this as malformed JSON.sendJson() – headers can't be sent after body. Set them first.rex_response::cleanOutputBuffers() – stray output from boot.php (warnings, debug dump() calls) leaks into the response.rex_config::get('my_addon', 'api_key').rex_api_my_addon_save_item must be called as ?rex-api-call=my_addon_save_item, not save_item or my_addon/save_item.$_POST – $_POST is only populated for application/x-www-form-urlencoded or multipart/form-data. For application/json, read php://input.