Skip to content

Commit 824a94e

Browse files
committed
Added Content Negotiation docs
1 parent 0bfa470 commit 824a94e

1 file changed

Lines changed: 124 additions & 1 deletion

File tree

user_guide_src/source/libraries/content_negotiation.rst

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,127 @@
22
Content Negotiation
33
*******************
44

5-
TODO
5+
Content negotiation is a way to determine what type of content to return to the client based on what the client
6+
can handle, and what the server can handle. This can be used to determine whether the client is wanting HTML or JSON
7+
returned, whether the image should be returned as a jpg or png, what type of compression is supported and more. This
8+
is done by analyzing four different headers which can each support multiple value options, each with their own priority.
9+
Trying to match this up manually can be pretty challenging. CodeIgniter provides the ``Negotiator`` class that
10+
can handle this for you.
11+
12+
=================
13+
Loading the Class
14+
=================
15+
16+
You can load an instance of the class manually through the Service class::
17+
18+
$negotiator = Config\Services::negotiator();
19+
20+
This will grab the current request instance and automatically inject it into the Negotiator class.
21+
22+
This class does not need to be loaded on it's own. Instead, it can be accessed through this request's ``IncomingRequest``
23+
instance. While you cannot access it directly this way, you can easily access all of methods through the ``negotiate()``
24+
method::
25+
26+
$request->negotiate('media', ['foo', 'bar']);
27+
28+
When accessed this way, the first parameter is the type of content you're trying to find a match for, while the
29+
second is an array of supported values.
30+
31+
===========
32+
Negotiating
33+
===========
34+
35+
In this section we will discuss the 4 types of content that can be negotiated and show how that would look using
36+
both of the methods described above to access the negotiator.
37+
38+
Media
39+
=====
40+
41+
The first aspect to look at is handling 'media' negotiations. These are provided by the ``Accept`` header and
42+
is one of the most complex headers available. A common example is the client telling the server what format it
43+
wants the data in. This is especially common in API's. For example, a client might request JSON formatted data
44+
from an API endpoint::
45+
46+
GET /foo HTTP/1.1
47+
Accept: application/json
48+
49+
The server now needs to provide a list of what type of content it can provide. In this example, the API might
50+
be able to return data as raw HTML, JSON, or XML. This list should be provided in order of preference.::
51+
52+
$supported = [
53+
'application/json',
54+
'text/html',
55+
'application/xml'
56+
];
57+
58+
$format = $request->negotiate('media', $supported);
59+
// or
60+
$format = $negotiate->media($supported);
61+
62+
In this case, both the client and the server can agree on formatting the data as JSON so 'json' is returned from
63+
the negotiate method. By default, if no match is found, the first element in the $supported array would be returned.
64+
In some cases, though, you might need to enforce the format to be a strict match. If you pass ``true`` as the
65+
final value, it will return an empty string if no match is found::
66+
67+
$format = $request->negotiate('media', $supported, true);
68+
// or
69+
$format = $negotiate->media($supported, true);
70+
71+
Language
72+
========
73+
74+
Another common usage is to determine the language the content should be served in. If you are running only a single
75+
language site, this obviously isn't going to make much difference, but any site that can offer up multiple translations
76+
of content will find this useful, since the browser will typically send the preferred language along in the ``Accept-Language``
77+
header::
78+
79+
GET /foo HTTP/1.1
80+
Accept-Language: fr; q=1.0, en; q=0.5
81+
82+
In this example, the browser would prefer french, with a second choice of english. If your website supports english
83+
and german you would do something like::
84+
85+
$supported = [
86+
'en',
87+
'de'
88+
];
89+
90+
$lang = $request->negotiate('language', $supported);
91+
// or
92+
$lang = $negotiate->language($supported);
93+
94+
In this example, 'en' would be returned as the current language. If no match is found, it will return the first element
95+
in the $supported array, so that should always be the preferred language.
96+
97+
Encoding
98+
========
99+
100+
The ``Accept-Encoding`` header contains the character sets the client prefers to receive, and is used to
101+
specify the type of compression the client supports::
102+
103+
GET /foo HTTP/1.1
104+
Accept-Encoding: compress, gzip
105+
106+
Your web server will define what types of compression you can use. Some, like Apache, only support **gzip**::
107+
108+
$type = $request->negotiate('encoding', ['gzip']);
109+
// or
110+
$type = $negotiate->encoding(['gzip']);
111+
112+
See more at `Wikipedia <https://en.wikipedia.org/wiki/HTTP_compression>`_.
113+
114+
Character Set
115+
=============
116+
117+
The desired character set is passed through the ``Accept-Charset`` header::
118+
119+
GET /foo HTTP/1.1
120+
Accept-Charset: utf-16, utf-8
121+
122+
By default, if no matches are found, **utf-8** will be returned::
123+
124+
$charset = $request->negotiate('charset', ['utf-8']);
125+
// or
126+
$charset = $negotiate->charset(['utf-8']);
127+
128+

0 commit comments

Comments
 (0)