Skip to content

Commit

Permalink
Merge pull request #78 from dotkernel/versions
Browse files Browse the repository at this point in the history
updated content negotiation page
  • Loading branch information
arhimede authored Nov 27, 2024
2 parents 5607895 + 666df54 commit 58555e6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 47 deletions.
76 changes: 30 additions & 46 deletions docs/book/v5/core-features/content-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@
**Content Negotiation** is performed by an application in order :

- To match the requested representation as specified by the client via the Accept header with a representation the
application can deliver.
- To match the requested format as specified by the client via the `Accept` header with a format the application can deliver.
- To determine the `Content-Type` of incoming data and deserialize it so the application can utilize it.

Essentially, content negotiation is the *client* telling the server what it is sending and what it wants in return, and
the server determining if it can do what the client requests.
Essentially, content negotiation is the *client* telling the server what it is sending and what it wants in return, and the server determining if it can do what the client requests.

Content negotiation validation in **Dotkernel API** happens through middleware, and it ensures that the incoming
request and the outgoing response conform to the content types specified in the config file for all routes or for a
specific route.

It performs validation on the `Accept` and `Content-Type` headers of the request and response and returning appropriate
errors responses when necessary.
Content negotiation validation in **Dotkernel API** happens through middleware, and it ensures that the incoming request and the outgoing response conform to the content types specified in the config file for all routes or for a specific route.
It performs validation on the `Accept` and `Content-Type` headers of the request and response.
It returns appropriate errors responses when necessary.

## Configuration

In Dotkernel API the configuration file for content negotiation is held
in `config/autoload/content-negotiation.global.php`
and the array looks like this:
In Dotkernel API the configuration file for content negotiation is `config/autoload/content-negotiation.global.php`.
The contents look like this:

```php
return [
Expand All @@ -45,43 +39,37 @@ return [
];
```

Except the `default` key, all your keys must match the route name, for example in Dotkernel API we have the route to
list all admins, which name is `admin.list`.

If you did not specify a route name to configure your specifications about content negotiation, the `default` one will
be in place. The `default` key is `mandatory`.
Excepting the `default` key, all your keys must match the route name.
For example, in Dotkernel API we have the route to list all admins, whose name is `admin.list`.
If you did not specify content negotiation for a given route, the `default` setup will be used.
The `default` key is mandatory.

Every route configuration must come with `Accept` and `Content-Type` keys, basically this will be the keys that the
request headers will be validated against.
Every route configuration must come with `Accept` and `Content-Type` keys.
These keys will be used as request headers for validation.

## Accept Negotiation

This specifies that your server can return that representation, or at least one of the representation sent by the
client.
This specifies that your server can return that format, or at least one of the formats sent by the client.

```shell
GET /admin HTTP/1.1
Accept: application/json
```

This request indicates the client wants `application/json` in return. Now the server, through the config file will try
to validate if that representation can be returned, basically if `application/json` is presented in the `Accept` key.
This request indicates the client wants `application/json` in return.
The server will use the config file to see if that format can be returned, basically if `application/json` is present in the `Accept` key.

If the representation cannot be returned, a status code `406 - Not Acceptable` will be returned.
- If the format cannot be returned, a status code `406 - Not Acceptable` will be returned.
- If the format can be returned, the server should report the media type through the `Content-Type` header in the response.

If the representation can be returned, the server should report the media type through `Content-Type` header of the
response.
> Due to how these validations are made, the server can return a more generic media type, e.g. for a `json` media type.
> For example, if the client sends `Accept: application/vnd.api+json`, but you configured your `Accept` key as `application/json`, the format will still be returned as `json`.
> Due to how these validations are made, for a `json` media type, the server can return a more generic media type,
> for example, if the clients send `Accept: application/vnd.api+json` and you configured your `Accept` key
> as `application/json` the representation will still be returned as `json`.
> If the `Accept` header of the request contains `*/*` it means that whatever the server can return it is OK, so it can
> return anything.
> If the `Accept` header of the request contains `*/*` it means that whatever format the server can return is OK.
## Content-Type Negotiation

The second aspect of content negotiation is the `Content-Type` header and determine the server can deserialize the data.
The second aspect of content negotiation is the `Content-Type` header and to determine if the server can deserialize the data.

```shell
POST /admin/1 HTTP/1.1
Expand All @@ -92,23 +80,19 @@ Content-Type: application/json
}
```

The server will try to validate the `Content-Type` header against your configured `Content-Type` key from the config
file, and if the format is not supported, a status code `415 - Unsupported Media Type` will be returned.
The server will try to validate the `Content-Type` header against your configured `Content-Type` key from the config file, and if the format is not supported, a status code `415 - Unsupported Media Type` will be returned.

For example, if you have a route that needs a file to be uploaded , normally you will configure the `Content-Type` of
that route to be `multipart/form-data`. The above request will fail as the client send `application/json` as
For example, if you have a route that needs a file to be uploaded, normally you will configure the `Content-Type` of that route to be `multipart/form-data`.
The above request will fail because the client sends `application/json` as
`Content-Type`.

> If the request does not contain "Content-Type" header, that means that the server will try to deserialize the data as
> it can.
> If the request does not contain a "Content-Type" header, that means that the server will try to deserialize the data to the best of its abilities.
## The `Request <-> Response` validation

In addition to the validation described above, a third one is happening and is the last one: the server will check if
the request `Accept` header can really be returned by the response.

Through the way **Dotkernel API** is returning a response in handler, a content type is always set.
In addition to the validation described above, a third and last one occurs.
The server will check if the format in the `Accept` header for the request can be returned in the response.

This cannot be the case in any custom response but in any case the server will check what `Content-Type` the response is
returning and will try to validate that against the `Accept` header of the request.
The way **Dotkernel API** returns a response in handler means a content type is always set.
This cannot be the case in any custom response, but the server will always check the `Content-Type` for the response and will try to validate that against the `Accept` header of the request.
If the validation fails, a status code `406 - Not Acceptable` will be returned.
2 changes: 1 addition & 1 deletion docs/book/v5/introduction/file-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ When using Dotkernel API the following structure is installed by default:

## `bin` folder

This folder contents are
This folder contains:

* `clear-config-cache.php` - Removes the config cache file `data/cache/config-cache.php`; available only when development mode is enabled
* `cli.php` - Used to build console applications based on [laminas-cli](https://github.com/laminas/laminas-cli)
Expand Down

0 comments on commit 58555e6

Please sign in to comment.