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
- one or several input denormalizers 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 the
Content-Type
header (optional) - one or several new value classes to represent the controller action result, their normalizers to help the generator to turn this into XML or JSON, and potentially one or several new media types to claim in the
Accept
header the desired value (optional) - the addition of this resource route to the REST root (optional)
In the following example, you add a greeting resource to the REST API.
It's 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 |
|
The controller.service_arguments
tag declares the controller as a service receiving injections.
It helps the autowiring of the serializer in the constructor.
The ibexa.api_platform.resource
tag declares the service as an API Platform resource.
Controller action¶
A REST controller should:
- return an object (passed automatically to a normalizer) or a
Response
(to customize it further) - extend
Ibexa\Rest\Server\Controller
- to inherit useful methods and properties like
repository
orrouter
- to be part of the OpenAPI Description
- to inherit useful methods and properties like
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
HTTP Cache
If the returned value was depending on a location, it could have been wrapped in aCachedValue
to be cached by the reverse proxy (like Varnish or Fastly) for future calls.
CachedValue
is used as following:
1 2 3 4 |
|
Value and Normalizer¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 |
|
A normalizer must implement the supportsNormalization
and normalize
methods.
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 33 34 35 36 37 38 39 40 |
|
Input denormalizer¶
A REST resource could use route parameters to handle input, but this example illustrates the usage of denormalized payload.
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 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
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 |
|
Describe resource in OpenAPI schema¶
Thanks to API Platform, you can document the OpenAPI resource directly from its controller through annotations.
The resource is added to the OpenAPI Description dumped with ibexa:openapi
command.
In dev
mode, the resource appears in the live documentation at <dev-domain>/api/ibexa/v2/doc#/App/api_greet_get
.
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
|
The resource can be tested from the live documentation.
For example, the POST /greet
at <dev-domain>/api/ibexa/v2/doc#/App/api_greet_post
can be tested this way:
- Click the Try it out button
- In Request body section, choose the Content-Type from the drop-down menu. For example, the JSON format
application/vnd.ibexa.api.GreetingInput+json
- In the text area, edit the JSON to make your own test
- In the Responses section, choose the desired response format for successful
200
- Click the Execute button
Eventually, remove properties to see if default values work, inject parse errors, or empty the whole text area to see error handling.
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 the following 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.
This example adds the following entry to the root XML output:
1 |
|