Skip to content

Commit 4072445

Browse files
committed
Merge 3.2
2 parents 814deaf + ea06124 commit 4072445

32 files changed

+216
-106
lines changed

admin/openapi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ To use it, use the `OpenApiAdmin` component, with the entrypoint of the API and
88
import { OpenApiAdmin } from "@api-platform/admin";
99

1010
export default () => (
11-
<OpenApiAdmin entrypoint="https://demo.api-platform.com" docEntrypoint="https://demo.api-platform.com/docs.json" />
11+
<OpenApiAdmin entrypoint="https://demo.api-platform.com" docEntrypoint="https://demo.api-platform.com/docs.jsonopenapi" />
1212
);
1313
```
1414

admin/real-time-mercure.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { OpenApiAdmin } from "@api-platform/admin";
1818
export default () => (
1919
<OpenApiAdmin
2020
entrypoint="https://demo.api-platform.com"
21-
docEntrypoint="https://demo.api-platform.com/docs.json"
21+
docEntrypoint="https://demo.api-platform.com/docs.jsonopenapi"
2222
mercure={{ hub: "https://mercure.rocks/hub" }}
2323
/>
2424
);

core/content-negotiation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Using the raw JSON or raw XML formats is discouraged, prefer using JSON-LD inste
99

1010
API Platform also supports [JSON Merge Patch (RFC 7396)](https://tools.ietf.org/html/rfc7396) the JSON:API [`PATCH`](https://tools.ietf.org/html/rfc5789) formats, as well as [Problem Details (RFC 7807)](https://tools.ietf.org/html/rfc7807), Hydra and JSON:API error formats.
1111

12-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/formats?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Formats screencast"><br>Watch the Formats screencast</a></p>
12+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/formats?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Formats screencast"><br>Watch the Formats screencast</a></p>
1313

1414
API Platform will automatically detect the best resolving format depending on:
1515

core/errors.md

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,39 @@ API Platform automatically sends the appropriate HTTP status code to the client:
66
unexpected ones. It also provides a description of the error in [the Hydra error format](https://www.hydra-cg.com/spec/latest/core/#description-of-http-status-codes-and-errors)
77
or in the format described in the [RFC 7807](https://tools.ietf.org/html/rfc7807), depending of the format selected during the [content negotiation](content-negotiation.md).
88

9-
## Converting PHP Exceptions to HTTP Errors
9+
# Errors
10+
11+
## Backward compatibility with < 3.1
12+
13+
Use the following configuration:
14+
15+
```yaml
16+
api_platform:
17+
defaults:
18+
rfc_7807_compliant_errors: false
19+
```
20+
21+
This can also be configured on an `ApiResource` or in an `HttpOperation`, for example:
22+
23+
```php
24+
#[ApiResource(extraProperties: ['rfc_7807_compliant_errors' => false])
25+
```
26+
27+
## Exception status code decision
28+
29+
There are many ways of configuring the exception status code we recommend reading the guides on how to use an [Error Provider](/docs/guides/error-provider) or create an [Error Resource](/docs/guides/error-resource).
30+
31+
1. we look at `exception_to_status` and take one if there's a match
32+
2. If your exception is a `Symfony\Component\HttpKernel\Exception\HttpExceptionInterface` we get its status.
33+
3. If the exception is a `ApiPlatform\Metadata\Exception\ProblemExceptionInterface` and there is a status we use it
34+
4. Same for `ApiPlatform\Metadata\Exception\HttpExceptionInterface`
35+
5. We have some defaults:
36+
- `Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface` => 400
37+
- `ApiPlatform\Validator\Exception\ValidationException` => 422
38+
6. the status defined on an `ErrorResource`
39+
7. 500 is the fallback
40+
41+
## Exception to status
1042

1143
The framework also allows you to configure the HTTP status code sent to the clients when custom exceptions are thrown
1244
on an API Platform resource operation.
@@ -101,14 +133,14 @@ the error will be returned in this format as well:
101133
}
102134
```
103135

104-
## Message Scope
136+
### Message Scope
105137

106138
Depending on the status code you use, the message may be replaced with a generic one in production to avoid leaking unwanted information.
107139
If your status code is >= 500 and < 600, the exception message will only be displayed in debug mode (dev and test). In production, a generic message matching the status code provided will be shown instead. If you are using an unofficial HTTP code, a general message will be displayed.
108140

109141
In any other cases, your exception message will be sent to end users.
110142

111-
## Fine-grained Configuration
143+
### Fine-grained Configuration
112144

113145
The `exceptionToStatus` configuration can be set on resources and operations:
114146

@@ -140,3 +172,106 @@ class Book
140172

141173
Exceptions mappings defined on operations take precedence over mappings defined on resources, which take precedence over
142174
the global config.
175+
176+
## Control your exceptions
177+
178+
With `rfc_7807_compliant_errors` a few things happen. First Hydra exception are compatible with the JSON Problem specification. Default exception that are handled by API Platform in JSON will be returned as `application/problem+json`.
179+
180+
To customize the API Platform response, replace the `api_platform.state.error_provider` with your own provider:
181+
182+
```php
183+
<?php
184+
185+
namespace App\State;
186+
187+
use ApiPlatform\Metadata\Operation;
188+
use ApiPlatform\State\ApiResource\Error;
189+
use ApiPlatform\State\ProviderInterface;
190+
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
191+
use Symfony\Component\DependencyInjection\Attribute\AsTaggedItem;
192+
193+
#[AsAlias('api_platform.state.error_provider')]
194+
#[AsTaggedItem('api_platform.state.error_provider')]
195+
final class ErrorProvider implements ProviderInterface
196+
{
197+
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
198+
{
199+
$request = $context['request'];
200+
$format = $request->getRequestFormat();
201+
$exception = $request->attributes->get('exception');
202+
203+
/** @var \ApiPlatform\Metadata\HttpOperation $operation */
204+
$status = $operation->getStatus() ?? 500;
205+
// You don't have to use this, you can use a Response, an array or any object (preferably a resource that API Platform can handle).
206+
$error = Error::createFromException($exception, $status);
207+
208+
// care about hiding informations as this can be a security leak
209+
if ($status >= 500) {
210+
$error->setDetail('Something went wrong');
211+
}
212+
213+
return $error;
214+
}
215+
}
216+
```
217+
218+
```yaml
219+
api_platform.state.error_provider:
220+
class: 'App\State\ErrorProvider'
221+
tags:
222+
- key: 'api_platform.state.error_provider'
223+
name: 'api_platform.state_provider'
224+
```
225+
226+
Note that our validation exception have their own error provider at:
227+
228+
```yaml
229+
api_platform.validator.state.error_provider:
230+
tags:
231+
- key: 'api_platform.validator.state.error_provider'
232+
name: 'api_platform.state_provider'
233+
```
234+
235+
## Domain exceptions
236+
237+
Another way of having full control over domain exceptions is to create your own Error resource:
238+
239+
```php
240+
<?php
241+
242+
namespace App\ApiResource;
243+
244+
use ApiPlatform\Metadata\ErrorResource;
245+
use ApiPlatform\Metadata\Exception\ProblemExceptionInterface;
246+
247+
#[ErrorResource]
248+
class Error extends \Exception implements ProblemExceptionInterface
249+
{
250+
public function getType(): string
251+
{
252+
return 'teapot';
253+
}
254+
255+
public function getTitle(): ?string
256+
{
257+
return null;
258+
}
259+
260+
public function getStatus(): ?int
261+
{
262+
return 418;
263+
}
264+
265+
public function getDetail(): ?string
266+
{
267+
return 'I am teapot';
268+
}
269+
270+
public function getInstance(): ?string
271+
{
272+
return null;
273+
}
274+
}
275+
```
276+
277+
We recommend using the `\ApiPlatform\Metadata\Exception\ProblemExceptionInterface` and the `\ApiPlatform\Metadata\Exception\HttpExceptionInterface`. For security reasons we add: `normalizationContext: ['ignored_attributes' => ['trace', 'file', 'line', 'code', 'message', 'traceAsString']]` because you usually don't want these. You can override this context value if you want.

core/extending-jsonld-context.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## JSON-LD
44

5-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/json-ld?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="JSON-LD screencast"><br>Watch the JSON-LD screencast</a></p>
5+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/json-ld?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="JSON-LD screencast"><br>Watch the JSON-LD screencast</a></p>
66

77
API Platform provides the possibility to extend the JSON-LD context of properties. This allows you to describe JSON-LD-typed
88
values, inverse properties using the `@reverse` keyword and you can even overwrite the `@id` property this way. Everything you define
@@ -63,7 +63,7 @@ Note that you do not have to provide the `@id` attribute. If you do not provide
6363

6464
## Hydra
6565

66-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/hydra?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Hydra screencast"><br>Watch the Hydra screencast</a></p>
66+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/hydra?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Hydra screencast"><br>Watch the Hydra screencast</a></p>
6767

6868
It's also possible to replace the Hydra context used by the documentation generator:
6969

core/extending.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ For instance, if you want to send a mail after a resource has been persisted, bu
3535

3636
To replace existing API Platform services with your decorators, [check out how to decorate services](https://symfony.com/doc/current/service_container/service_decoration.html).
3737

38-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform-security/service-decoration?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Service Decoration screencast"><br>Watch the Service Decoration screencast</a></p>
38+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform-security/service-decoration?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Service Decoration screencast"><br>Watch the Service Decoration screencast</a></p>

core/filters.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ By default, all filters are disabled. They must be enabled explicitly.
1212
When a filter is enabled, it automatically appears in the [OpenAPI](openapi.md) and [GraphQL](graphql.md) documentations.
1313
It is also automatically documented as a `hydra:search` property for JSON-LD responses.
1414

15-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/filters?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Filtering and Searching screencast"><br>Watch the Filtering & Searching screencast</a></p>
15+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/filters?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Filtering and Searching screencast"><br>Watch the Filtering & Searching screencast</a></p>
1616

1717
## Doctrine ORM and MongoDB ODM Filters
1818

core/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ and what [JSON-LD](https://json-ld.org/) and [Hydra](https://www.hydra-cg.com/)
3030

3131
## Mapping the Entities
3232

33-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/api-resource?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="Create an API Resource screencast"><br>Watch the Create an API Resource screencast</a></p>
33+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/api-resource?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="Create an API Resource screencast"><br>Watch the Create an API Resource screencast</a></p>
3434

3535
API Platform is able to automatically expose entities mapped as "API resources" through a REST API supporting CRUD
3636
operations.

core/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ This bundle is extensively tested (unit and functional). The [`Fixtures/` direct
4343

4444
## Screencasts
4545

46-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/tracks/rest?cid=apip#api-platform"><img src="../distribution/images/symfonycasts-player.png" alt="SymfonyCasts, API Platform screencasts"></a></p>
46+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/tracks/rest?cid=apip#api-platform"><img src="/docs/distribution/images/symfonycasts-player.png" alt="SymfonyCasts, API Platform screencasts"></a></p>
4747

4848
The easiest and funniest way to learn how to use API Platform is to watch [the more than 60 screencasts available on SymfonyCasts](https://symfonycasts.com/tracks/rest?cid=apip#api-platform)!

core/jwt.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The tokens are signed by the server's key, so the server is able to verify that
77
88
API Platform allows to easily add a JWT-based authentication to your API using [LexikJWTAuthenticationBundle](https://github.com/lexik/LexikJWTAuthenticationBundle).
99

10-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/symfony-rest4/json-web-token?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="JWT screencast"><br>Watch the LexikJWTAuthenticationBundle screencast</a></p>
10+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/symfony-rest4/json-web-token?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="JWT screencast"><br>Watch the LexikJWTAuthenticationBundle screencast</a></p>
1111

1212
## Installing LexikJWTAuthenticationBundle
1313

@@ -116,7 +116,7 @@ also want to [configure Swagger UI for JWT authentication](#documenting-the-auth
116116

117117
### Adding Authentication to an API Which Uses a Path Prefix
118118

119-
If your API uses a [path prefix](https://symfony.com/doc/current/routing/external_resources.html#prefixing-the-urls-of-imported-routes), the security configuration would look something like this instead:
119+
If your API uses a [path prefix](https://symfony.com/doc/current/routing/external_resources.html#route-groups-and-prefixes), the security configuration would look something like this instead:
120120

121121
```yaml
122122
# api/config/packages/security.yaml

0 commit comments

Comments
 (0)