Creating new REST resource¶
To create a new REST resource, you need to prepare:
- The REST route leading to a controller action.
- The controller and its action.
- Optionally, one or several
InputParser
objects if the controller needs to receive a payload to treat, one or several value classes to represent this payload and potentially one or several new media types to type this payload in theContent-Type
header. - Optionally, one or several new value classes to represent the controller action result, their
ValueObjectVisitor
to help the generator to turn this into XML or JSON and potentially one or several new media types to claim in theAccept
header the desired value. - Optionally, the addition of this resource route to the REST root.
In the following example, you add a greeting resource to the REST API.
It is available through GET
and POST
methods. GET
sets default values while POST
allows inputting custom values.
Route¶
New REST routes should use the REST URI prefix for consistency.
To ensure that they do, in the config/routes.yaml
file, while importing a REST routing file, use ibexa.rest.path_prefix
parameter as a prefix
.
1 2 3 |
|
The config/routes_rest.yaml
file imported above is created with the following configuration:
1 2 3 4 |
|
CSRF protection¶
If a REST route is designed to be used with unsafe methods, the CSRF protection is enabled by default like for built-in routes.
You can disable it by using the route parameter csrf_protection
.
1 2 3 4 5 6 |
|
Controller¶
Controller service¶
You can use the following configuration to have all controllers from the App\Rest\Controller\
namespace (files in the src/Rest/Controller/
folder) to be set as REST controller services.
1 2 3 4 5 6 7 8 |
|
Having the REST controllers set as services enables using features such as the InputDispatcher
service in the Controller action.
Controller action¶
A REST controller should:
- return a value object and have a
Generator
andValueObjectVisitor
s producing the XML or JSON output; - extend
Ibexa\Rest\Server\Controller
to inherit utils methods and properties likeInputDispatcher
orRequestParser
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
If the returned value was depending on a Location, it could have been wrapped in a CachedValue
to be cached by the reverse proxy (like Varnish) for future calls.
CachedValue
is used in the following way:
1 2 3 4 |
|
Value and ValueObjectVisitor¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
A ValueObjectVisitor
must implement the visit
method.
Argument | Description |
---|---|
$visitor |
The output visitor. Can be used to set custom response headers ( setHeader ), HTTP status code ( setStatus ) |
$generator |
The actual response generator. It provides you with a DOM-like API. |
$data |
The visited data. The exact object that you returned from the controller. It can't have a type declaration because the method signature is shared. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
The Values/Greeting
class is linked to its ValueObjectVisitor
through the service tag.
1 2 3 4 5 6 |
|
Here, the media type is application/vnd.ibexa.api.Greeting
plus a format. To have a different vendor than the default, you could create a new Output\Generator
or hard-code it in the ValueObjectVisitor
like in the RestLocation
example.
InputParser¶
A REST resource could use route parameters to handle input, but this example illustrates the usage of an input parser.
For this example, the structure is a GreetingInput
root node with two leaf nodes, Salutation
and Recipient
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Here, this InputParser
directly returns the right value object.
In other cases, it could return whatever object is needed to represent the input for the controller to perform its action, like arguments to use with a Repository service.
1 2 3 4 5 6 |
|
Testing the new resource¶
Now you can test both GET
and POST
methods, and both XML
and JSON
format for inputs and outputs.
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Registering resources in REST root¶
You can add the new resource to the root resource through a configuration with the following pattern:
1 2 3 4 5 6 7 |
|
The router.generate
renders a URI based on the name of the route and its parameters. The parameter values can be a real value or a placeholder. For example, 'router.generate("ibexa.rest.load_location", {locationPath: "1/2"})'
results in /api/ibexa/v2/content/locations/1/2
while 'router.generate("ibexa.rest.load_location", {locationPath: "{locationPath}"})'
gives /api/ibexa/v2/content/locations/{locationPath}
.
This syntax is based on Symfony's expression language, an extensible component that allows limited/readable scripting to be used outside the code context.
In this example, app.rest.greeting
is available in every SiteAccess (default
):
1 2 3 4 5 6 7 |
|
You can place this configuration in any regular config file, like the existing config/packages/ibexa.yaml
, or a new config/packages/ibexa_rest.yaml
file.
The above example adds the following entry to the root XML output:
1 |
|