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

core/mongodb.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ docker compose build php
4343
Add a MongoDB image to the docker-compose file:
4444

4545
```yaml
46-
# docker-compose.yml
47-
# ...
46+
# compose.yaml
47+
48+
services:
49+
# ...
4850
db-mongodb:
4951
# In production, you may want to use a managed database service
5052
image: mongo

core/openapi.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ API Platform natively supports the [OpenAPI](https://www.openapis.org/) API spec
44

55
![Screenshot](../distribution/images/swagger-ui-1.png)
66

7-
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/open-api-spec?cid=apip"><img src="../distribution/images/symfonycasts-player.png" alt="OpenAPI screencast"><br>Watch the OpenAPI screencast</a></p>
7+
<p align="center" class="symfonycasts"><a href="https://symfonycasts.com/screencast/api-platform/open-api-spec?cid=apip"><img src="/docs/distribution/images/symfonycasts-player.png" alt="OpenAPI screencast"><br>Watch the OpenAPI screencast</a></p>
88

9-
The specification of the API is available at the `/docs.json` path.
9+
The specification of the API is available at the `/docs.jsonopenapi` path.
1010
By default, OpenAPI v3 is used.
11-
You can also get an OpenAPI v3-compliant version thanks to the `spec_version` query parameter: `/docs.json?spec_version=3`
11+
You can also get an OpenAPI v3-compliant version thanks to the `spec_version` query parameter: `/docs.jsonopenapi?spec_version=3`
1212

1313
It also integrates a customized version of [Swagger UI](https://swagger.io/swagger-ui/) and [ReDoc](https://rebilly.github.io/ReDoc/), some nice tools to display the
1414
API documentation in a user friendly way.
@@ -583,7 +583,7 @@ You may want to copy the [one shipped with API Platform](https://github.com/api-
583583
[AWS API Gateway](https://aws.amazon.com/api-gateway/) supports OpenAPI partially, but it [requires some changes](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html).
584584
API Platform provides a way to be compatible with Amazon API Gateway.
585585

586-
To enable API Gateway compatibility on your OpenAPI docs, add `api_gateway=true` as query parameter: `http://www.example.com/docs.json?api_gateway=true`.
586+
To enable API Gateway compatibility on your OpenAPI docs, add `api_gateway=true` as query parameter: `http://www.example.com/docs.jsonopenapi?api_gateway=true`.
587587
The flag `--api-gateway` is also available through the command-line.
588588

589589
## OAuth

core/operation-path-naming.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ Pre-registered resolvers are available and can easily be overridden.
77

88
There are two pre-registered operation path naming services:
99

10-
Service name | Entity name | Path result
11-
------------------------------------------------------|--------------|----------------
12-
`api_platform.path_segment_name_generator.underscore` | `MyResource` | `/my_resources`
13-
`api_platform.path_segment_name_generator.dash` | `MyResource` | `/my-resources`
10+
Service name | Entity name | Path result
11+
---------------------------------------------------------------|--------------|----------------
12+
`api_platform.metadata.path_segment_name_generator.underscore` | `MyResource` | `/my_resources`
13+
`api_platform.metadata.path_segment_name_generator.dash` | `MyResource` | `/my-resources`
1414

15-
The default resolver is `api_platform.path_segment_name_generator.underscore`.
15+
The default resolver is `api_platform.metadata.path_segment_name_generator.underscore`.
1616
To change it to the dash resolver, add the following lines to `api/config/packages/api_platform.yaml`:
1717

1818
```yaml
1919
# api/config/packages/api_platform.yaml
2020
api_platform:
21-
path_segment_name_generator: api_platform.path_segment_name_generator.dash
21+
path_segment_name_generator: api_platform.metadata.path_segment_name_generator.dash
2222
```
2323
2424
## Create a Custom Operation Path Resolver
@@ -27,14 +27,14 @@ Let's assume we need URLs without separators (e.g. `api.tld/myresources`)
2727

2828
### Defining the Operation Segment Name Generator
2929

30-
Make sure the custom segment generator implements [`ApiPlatform\Operation\PathSegmentNameGeneratorInterface`](https://github.com/api-platform/core/blob/main/src/Operation/PathSegmentNameGeneratorInterface.php):
30+
Make sure the custom segment generator implements [`ApiPlatform\Metadata\Operation\PathSegmentNameGeneratorInterface`](https://github.com/api-platform/core/blob/main/src/Metadata/Operation/PathSegmentNameGeneratorInterface.php):
3131

3232
```php
3333
<?php
3434
// api/src/Operation/SingularPathSegmentNameGenerator.php
3535
namespace App\Operation;
3636
37-
use ApiPlatform\Operation\PathSegmentNameGeneratorInterface;
37+
use ApiPlatform\Metadata\Operation\PathSegmentNameGeneratorInterface;
3838
3939
class SingularPathSegmentNameGenerator implements PathSegmentNameGeneratorInterface
4040
{

core/operations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
API Platform relies on the concept of operations. Operations can be applied to a resource exposed by the API. From
44
an implementation point of view, an operation is a link between a resource, a route and its related controller.
55

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

88
API Platform automatically registers typical [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) operations
99
and describes them in the exposed documentation (Hydra and Swagger). It also creates and registers routes corresponding

0 commit comments

Comments
 (0)