aboutsummaryrefslogtreecommitdiff
path: root/files/fr/web/api/fetch_api/using_fetch/index.md
blob: 922a2902880140eb38d6c7727c46a569ce3c09e6 (plain)
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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
---
title: Utiliser Fetch
slug: Web/API/Fetch_API/Using_Fetch
tags:
  - API
  - BODY
  - Expérimental(2)
  - Fetch
  - Guide
  - Promesse
  - Promise
  - Response
  - request
translation_of: Web/API/Fetch_API/Using_Fetch
---
{{DefaultAPISidebar("Fetch API")}}

L'[API Fetch](/fr/docs/Web/API/Fetch_API) fournit une interface JavaScript pour l'accès et la manipulation des parties de la pipeline HTTP, comme les requêtes et les réponses. Cela fournit aussi une méthode globale {{domxref("GlobalFetch.fetch","fetch()")}} qui procure un moyen facile et logique de récupérer des ressources à travers le réseau de manière asynchrone.

Ce genre de fonctionnalité était auparavant réalisé avec {{domxref("XMLHttpRequest")}}. Fetch fournit une meilleure alternative qui peut être utilisée facilement par d’autres technologies comme {{domxref("ServiceWorker_API", "Service Workers")}}. Fetch fournit aussi un endroit unique et logique pour la définition d'autres concepts liés à HTTP comme CORS et les extensions d'HTTP.

## L'état actuel du support par les navigateurs

Le support de Fetch est à ses débuts, mais les choses progressent. Il a été activé par défaut sur Firefox 39 et supérieur, et sur Chrome 42 et supérieur.

Si vous souhaitez l'utiliser maintenant, il y a un [polyfill Fetch](https://github.com/github/fetch) disponible qui recrée la fonctionnalité pour les navigateurs qui ne le supportent pas. Gardez à l'esprit qu'il est au stade expérimental et pas encore complètement fonctionnel.

> **Note :** Certaines préoccupations ont été soulevées sur le fait que la [spécification de Fetch](https://fetch.spec.whatwg.org/) est en contradition avec la [spécification de Streams](https://streams.spec.whatwg.org/); cependant, les prévisions montrent une intention d'intégrer Streams avec Fetch: pour plus d'informations reportez vous à [Fetch API integrated with Streams](https://github.com/yutakahirano/fetch-with-streams/).

## Détection de la fonctionnalité

Le support de l'API Fetch peut être détecté en vérifiant l'existence de {{domxref("Headers")}}, {{domxref("Request")}}, {{domxref("Response")}} ou {{domxref("GlobalFetch.fetch","fetch()")}} sur la portée de {{domxref("Window")}} ou de {{domxref("Worker")}}. Par exemple, vous pouvez faire cela dans votre script :

```js
if (window.fetch) {
    // exécuter ma requête fetch ici
} else {
    // Faire quelque chose avec XMLHttpRequest?
}
```

## Créer une requête fetch

Une requête fetch basique est vraiment simple à initier. Jetez un coup d'œil au code suivant :

```js
const myImage = document.querySelector('img');

fetch('flowers.jpg')
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  const objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});
```

Ici nous récupérons une image à travers le réseau et l'insérons dans un élément {{htmlelement("img")}}. L'utilisation la plus simple de `fetch()` prend un argument — le chemin de la ressource que nous souhaitons récupérer — et retourne une promesse (promise) contenant, en réponse, un objet (de type {{domxref("Response")}}).

Bien sûr, il s'agit seulement d'une réponse HTTP, pas exactement de l'image. Pour extraire le contenu de l'image de la réponse, nous utilisons la méthode {{domxref("Body.blob","blob()")}} (définie sur le mixin {{domxref("Body")}}, qui est implémenté autant par les objets {{domxref("Request")}} que par les objets {{domxref("Response")}}).

> **Note :** Le mixin Body a aussi des méthodes similaires pour extraire d'autres types contenu ; pour plus d'informations regardez la section {{anch("Corps")}}.

Un objet `objectURL` est ensuite créé à partir du {{domxref("Blob")}} extrait, puis est inseré dans {{domxref("img")}}.

Les requêtes Fetch sont controllées par la directive `connect-src` du [Content Security Policy](/fr/docs/Security/CSP/CSP_policy_directives) plutôt que par la directive de la ressource dont il s’agit de la récupération.

### Fournir des options à la requête

La méthode `fetch()` accepte un second paramètre, optionnel ; un objet `init` qui vous permet de contrôler un certain nombre de réglages :

```js
var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

fetch('flowers.jpg',myInit)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});
```

Reportez-vous à {{domxref("GlobalFetch.fetch","fetch()")}} pour la liste complète des options disponibles, et plus de détails.

### Vérifier que la récupération a réussi

Une promesse {{domxref("GlobalFetch.fetch","fetch()")}} va retourner une {{jsxref("TypeError")}} quand un problème réseau s'est produit. Cependant, il peut aussi s'agir d'un problème de permission ou quelque chose de similaire — un code HTTP 404 ne constitue pas une erreur réseau, par exemple. Un bon test de la réussite de `fetch()` devrait inclure la vérification que la promesse soit résolue, puis vérifier que la propriété {{domxref("Response.ok")}} ait la valeur _true_. Le code devrait ressembler à ce qui suit:

```js
fetch('flowers.jpg').then(function(response) {
  if(response.ok) {
    response.blob().then(function(myBlob) {
      var objectURL = URL.createObjectURL(myBlob);
      myImage.src = objectURL;
    });
  } else {
    console.log('Mauvaise réponse du réseau');
  }
})
.catch(function(error) {
  console.log('Il y a eu un problème avec l\'opération fetch: ' + error.message);
});
```

### Fournir votre propre objet requête

Plutôt que de transmettre le chemin de la ressource que vous souhaitez récupérer avec l'appel `fetch()`, vous pouvez créer un objet de requête en utilisant le constructeur {{domxref("Request.Request","Request()")}}, et le transmettre à la méthode `fetch()` en tant qu’argument:

```js
var myHeaders = new Headers();

var myInit = { method: 'GET',
               headers: myHeaders,
               mode: 'cors',
               cache: 'default' };

var myRequest = new Request('flowers.jpg',myInit);

fetch(myRequest,myInit)
.then(function(response) {
  return response.blob();
})
.then(function(myBlob) {
  var objectURL = URL.createObjectURL(myBlob);
  myImage.src = objectURL;
});
```

`Request()` accepte exactement les mêmes paramètres que la méthode `fetch()`. Vous pouvez même lui transmettre un objet Request existant pour en créer une copie :

```js
var anotherRequest = new Request(myRequest,myInit);
```

C'est très pratique, si le corps de la requête et de la réponse ne sont utilisés qu'une fois seulement. Cette manière de faire une copie permet de ré-utiliser la requête/réponse, en changeant juste les options du `init` si nécessaire.

> **Note :** Il y a aussi une méthode {{domxref("Request.clone","clone()")}} qui créer une copie. Cela a une sémantique légèrement différente à l'autre méthode de copie— La première va échouer si l'ancien corps de la requête a déjà été lu (même pour copier une réponse), alors qu'avec `clone()` non.

## En-têtes (Headers)

L'interface {{domxref("Headers")}} vous permet de créer vos propres objets d'en-têtes via le constructeur {{domxref("Headers.Headers","Headers()")}}. Un objet en-tête est un simple ensemble de plusieurs clé-valeurs:

```js
var content = "Hello World";
var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
myHeaders.append("Content-Length", content.length.toString());
myHeaders.append("X-Custom-Header", "ProcessThisImmediately");
```

On peut atteindre le même résultat en transmettant un tableau de tableaux ou un objet littéral au constructeur:

```js
myHeaders = new Headers({
  "Content-Type": "text/plain",
  "Content-Length": content.length.toString(),
  "X-Custom-Header": "ProcessThisImmediately",
});
```

Le contenu peut être interrogé et récupéré:

```js
console.log(myHeaders.has("Content-Type")); // true
console.log(myHeaders.has("Set-Cookie")); // false
myHeaders.set("Content-Type", "text/html");
myHeaders.append("X-Custom-Header", "AnotherValue");

console.log(myHeaders.get("Content-Length")); // 11
console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]

myHeaders.delete("X-Custom-Header");
console.log(myHeaders.getAll("X-Custom-Header")); // [ ]
```

Certaines de ces opérations sont seulement utiles dans {{domxref("ServiceWorker_API","ServiceWorkers")}}, mais elles fournissent une bien meilleur API pour la manipulation des en-têtes.

Toutes les méthodes d'en-tête provoquent une erreur TypeError si un nom d’en-tête utilisé n'est pas un nom d’en-tête HTTP valide. Les opérations de mutation vont provoquer une erreur TypeError si il y a une protection immutable (voir ci-dessous). Sinon elles vont échouer en silence. Par exemple :

```js
var myResponse = Response.error();
try {
  myResponse.headers.set("Origin", "http://mybank.com");
} catch(e) {
  console.log("Ne peut pas prétendre être une banque!");
}
```

Un bon cas d'utilisation des en-têtes est de vérifier que le type de contenu récupéré est correct avant de poursuivre le traitement. Par exemple:

```js
fetch(myRequest).then(function(response) {
  var contentType = response.headers.get("content-type");
  if(contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(function(json) {
      // traitement du JSON
    });
  } else {
    console.log("Oops, nous n'avons pas du JSON!");
  }
});
```

### Protection (Guard)

Puisque les en-têtes peuvent être envoyés dans les requêtes et reçus dans les réponses, et ont diverses limitations sur quelles informations peuvent et doivent être mutables, les objets en-tête ont une propriété _guard_. Ce n'est pas exposé au Web, mais cela définit quelle opération de mutation est autorisée sur l'objet en-tête.

Les valeurs possibles de la propriété _guard_ sont:

- `none`: défaut.
- `request`: guard pour l’en-tête obtenu d'une requête ({{domxref("Request.headers")}}).
- `request-no-cors`: guard pour l'en-tête obtenu d'une requête créé avec {{domxref("Request.mode")}} `no-cors`.
- `response`: guard pour l'en-tête obtenu d'une réponse ({{domxref("Response.headers")}}).
- `immutable`: majoritairement utilisé pour les ServiceWorkers; retourne un objet en-tête en lecture seule.

> **Note :** Vous ne pouvez pas ajouter ou définir sur une requête protegée une en-tête `Content-Length`. De manière similaire, ajouter `Set-Cookie` dans l'en-tête de réponse n'est pas autorisé: les ServiceWorkers ne sont pas autorisés à gérer des cookies via des réponses synthétisées.

## Réponses

Comme vous l'avez vu ci-dessus, des instances de {{domxref("Response")}} sont retournées quand la promesse de `fetch()` est résolue.

Elles peuvent aussi être programmées dans le code via JavaScript, mais c'est seulement utile concernant les {{domxref("ServiceWorker_API", "ServiceWorkers")}}, quand vous retournez, pour une requête reçue, une réponse personnalisée en utilisant la méthode {{domxref("FetchEvent.respondWith","respondWith()")}}:

```js
var myBody = new Blob();

addEventListener('fetch', function(event) {
  event.respondWith(new Response(myBody, {
    headers: { "Content-Type" : "text/plain" }
  });
)});
```

Le constructeur {{domxref("Response.Response","Response()")}} prend deux arguments optionnels —le corps de la réponse, et un objet d'options (similaire à l'objet que {{domxref("Request.Request","Request()")}} accepte).

Les propriétés de réponse les plus communes que vous allez utiliser sont:

- {{domxref("Response.status")}} —Un entier (valeur par défaut 200) contenant le code de statut de la réponse.
- {{domxref("Response.statusText")}} — Une chaine de caractères (valeur par défaut "OK"), qui correspond au message du statut HTTP.
- {{domxref("Response.ok")}} —vu précedemment, c'est un raccourci pour vérifier que le code de statut et bien compris entre 200 et 299 inclus. Retourne un {{domxref("Boolean")}}.

> **Note :** La méthode statique {{domxref("Response.error","error()")}} retourne simplement une réponse d'erreur. De manière similaire, {{domxref("Response.redirect","redirect()")}} retourne une réponse de redirection vers une URL spécifique. Elles sont aussi pertinentes pour les Service Workers.

## Corps

Autant une requête qu'une réponse peut contenir un corps avec des données. Un corps est une instance de n'importe lequel des types suivants:

- {{domxref("ArrayBuffer")}}
- {{domxref("ArrayBufferView")}} (Uint8Array et ses proches)
- {{domxref("Blob")}}/Fichier
- chaine de caractères
- {{domxref("URLSearchParams")}}
- {{domxref("FormData")}}

Le mixin {{domxref("Body")}} définit les méthodes suivantes pour extraire le corps (implémenté autant par la {{domxref("Request")}} que par la {{domxref("Response")}}). Elles retournent toutes une promesse qui sera éventuellement résolue avec le contenu actuel.

- {{domxref("Body.arrayBuffer","arrayBuffer()")}}
- {{domxref("Body.blob","blob()")}}
- {{domxref("Body.json","json()")}}
- {{domxref("Body.text","text()")}}
- {{domxref("Body.formData","formData()")}}

Ceci rend l'usage de données non textuelles plus facile qu’avec XHR.

Le corps des requêtes peut être défini en passant les paramètres du corps:

```js
var form = new FormData(document.getElementById('login-form'));
fetch("/login", {
  method: "POST",
  body: form
})
```

Les Requêtes et Réponses (et par extension la fonction `fetch()`), vont tenter de déterminer le type de contenu. Une requête va automatiquement définir un en-tête `Content-Type`  si rien n'est défini dans le dictionnaire \[NDLT: configuration d'initialisation].

## Spécifications

| Spécification                | Statut                   | Commentaire         |
| ---------------------------- | ------------------------ | ------------------- |
| {{SpecName('Fetch')}} | {{Spec2('Fetch')}} | Définition initiale |

## Compatibilité navigateur

{{Compat("api.WindowOrWorkerGlobalScope.fetch")}}

## Voir aussi

- [API ServiceWorker](/fr/docs/Web/API/ServiceWorker_API)
- [HTTP access control (CORS)](/fr/docs/Web/HTTP/Access_control_CORS)
- [HTTP](/fr/docs/Web/HTTP)
- [Polyfill pour Fetch](https://github.com/github/fetch)
- [Exemples de Fetch sur Github](https://github.com/mdn/fetch-examples/)