Skip to main content

SpazioCodice

Dans cet article, nous allons voir comment utiliser la redirection URI 303 pour rendre les ressources disponibles aux machines et aux humain.

Redirection URI 303 pour le Web Sémantique

Lorsque je pense au Web Sémantique et à la négociation de contenu, je me souviens toujours de certains épisodes de mon enfance.

Souvent, pendant les vacances d’été, j’accompagnais mon père au marché pour faire des courses. J’étais heureux de l’aider, surtout parce que je savais qu’il y aurait aussi une occasion de visiter la confiserie ou la librairie de bandes dessinées, ou les deux.

Lorsque nous étions à la confiserie, j’étais impressionné par la manière dont l’homme au comptoir connaissait chaque client et à quelle vitesse il était prêt à donner les bonbons les plus demandés. Bien sûr, nous n’étions pas une exception, et je ressortais toujours rapidement du magasin avec mon butin de chocolat.

L’homme fournissait efficacement à chacun la forme de sucre qu’il préférait, en fonction de qui ils étaient et de leur format préféré.

Les techniques de négociation de contenu et de redirection URI fonctionnent de manière similaire dans le Web Sémantique, et nous allons voir comment nous pouvons obtenir les bonbons désirés en utilisant le protocole HTTP.

Aperçu

Tim Berners-Lee a imaginé le Web Sémantique comme un Web composé de données que les machines peuvent traiter, établissant ainsi l’axiome que la plupart de ces données doivent être lisibles par les machines.

Sur le Web Sémantique, l’information est exprimée sous forme de déclarations sur des ressources, comme par exemple « Les membres du groupe Eurythmics étaient Annie Lennox et Dave Stewart » et « Annie Lennox a écrit cette chanson ».

Le Resource Description Framework (RDF) a fait de ce système de modélisation son principe central.

Néanmoins, la même URI /people/Federico peut identifier à la fois ma page d’accueil et une représentation RDF de la ressource identifiée par la chaîne Federico.

Même le RDF utilise des URI (Uniform Resource Identifiers) pour identifier les ressources, ce qui nous amène à la question principale : puisque les URI peuvent identifier à la fois des pages web et des ressources lisibles par machine, comment les utilisons-nous pour que leur identification soit sans ambiguïté ?

Identifiants de Ressources, Ou Qu'est-ce Qu'il Y A Dans Une URI ?

Sur le Web Sémantique, les URI peuvent identifier des pages web et des objets. Ces objets peuvent appartenir au monde réel (comme les avions, les personnes ou les livres) ou être fictifs (comme les idées ou créatures fantastiques, telles que les hobbits ou le Millennium Falcon). Le Web Sémantique les appelle objets du monde réel ou choses.

D’après le document du W3C, Cool URIs for the Semantic Web (qui, à la demande des auteurs, doit être conservé en tant que document en cours de développement), il existe deux exigences principales concernant la manière dont les URI doivent être utilisées par rapport au Web Sémantique :

1. ÊTRE SUR LE WEB
Donné seulement une URI, les machines et les personnes devraient pouvoir récupérer une description de la ressource identifiée par l’URI depuis le Web. Un tel mécanisme de recherche est important pour établir une compréhension partagée de ce qu’une URI identifie. Les machines devraient obtenir des données RDF et les humains devraient obtenir une représentation lisible, comme HTML. Le protocole de transfert Web standard, HTTP, devrait être utilisé.

2. ÊTRE CLAIR
Il ne devrait y avoir aucune confusion entre les identifiants des documents Web et les identifiants des autres ressources. Les URI sont destinées à identifier seulement l’une de ces ressources, donc une URI ne peut pas désigner à la fois un document Web et un objet du monde réel.

En y réfléchissant un peu plus, ces principes semblent être en conflit : la meilleure manière d’offrir une URI décrivant un objet du monde réel (comme un auteur ou une œuvre) en tant que ressource RDF ou JSON et sa page web semble être d’utiliser la même URI pour toutes ces représentations.

Comment ces ressources pourraient-elles être différenciées, et comment le système doit-il comprendre quelle représentation spécifique de la ressource le client souhaite ?

C’est ici que la négociation de contenu entre en jeu.

Négociation de contenu

Comme mentionné précédemment, les représentations offertes pour la même ressource diffèrent considérablement. Il ne s’agit pas de plusieurs versions du même document, mais de documents complètement différents.

HTTP dispose d’un mécanisme puissant permettant d’offrir différents formats et versions linguistiques du même document Web, appelé négociation de contenu.

En général, lorsqu’un agent utilisateur (comme un navigateur) effectue une requête HTTP, il envoie des en-têtes HTTP pour indiquer les formats de données qu’il préfère. Le serveur sélectionne la meilleure correspondance dans son système de fichiers, génère le contenu souhaité à la demande et le renvoie au client.

Par exemple, un navigateur pourrait envoyer cette requête HTTP pour indiquer qu’il souhaite une représentation en HTML ou XHTML de https://my-site.org/people/Alice en anglais ou en allemand :

				
					GET /people/Alice HTTP/1.1
Host: my-site.org
Accept: text/html, application/xhtml+xml
Accept-Language: en
				
			

Et le serveur pourrait répondre :

				
					HTTP/1.1 303 See Other
Location: https://my-site.org/en/people/alice.html
				
			

Le serveur Web sera configuré pour répondre aux requêtes avec un code de statut 303 et un en-tête HTTP Location qui fournit l’URL d’un document représentant la ressource dans le format (et la langue, dans ce cas) demandé.

C’est ce que signifie la “négociation de contenu” : le serveur Web évalue la requête, inspecte les en-têtes envoyés avec elle, puis “négocie” la bonne correspondance pour le format et la langue demandés, renvoyant ainsi la ressource ou la réponse appropriée.

Puisque le code de statut 303 est un code de redirection, le serveur peut fournir l’emplacement du document représentant la ressource. Si, en revanche, une requête reçoit l’un des codes de statut habituels dans la plage 2XX, comme 200 OK, alors le client sait que l’URI identifie un document Web ou une ressource.

Ainsi, la négociation de contenu, dans son essence, est au cœur de l’exposition des ressources sur le Web Sémantique.

Plus loin dans cet article, nous verrons mieux comment la résolution d’URI fonctionne en utilisant la négociation de contenu dans certains cas d’exposition de ressources.

Comme le montre le diagramme ci-dessus, lors de la réception de la requête pour une ressource, le serveur inspecte les en-têtes et l’URI pour appliquer la négociation de contenu et déterminer la destination appropriée. Les deux en-têtes les plus intéressants que le serveur inspectera sont Accept et Accept-language. Cependant, le diagramme considère uniquement l’en-tête Accept. Remarquez la résolution finale si aucun format n’est reconnu pour la requête : un code de statut 406 (Not Acceptable) est retourné. C’est la meilleure stratégie de résolution pour les requêtes de format inconnu ou non géré, car une réponse au format par défaut (par exemple, HTML) ne communiquerait pas le message approprié aux clients, qui, sur le Web Sémantique, devraient toujours être conscients du format.

Exemples

Pour notre étude de cas, supposons qu’un client demande l’URI d’un livre, disons Harry Potter à l’école des sorciers, dans son édition hardcover, dont l’ID dans notre système correspond à l’ISBN du livre :

				
					https://my-site.org/books/9780780797086
				
			

Dans ce cas, notre client est un navigateur Web. Naturellement, lorsqu’un navigateur Web demande une ressource, parmi d’autres en-têtes, il envoie un en-tête Accept: contenant le type de média text/html (note : l’en-tête Accept: des navigateurs spécifie généralement une liste séparée par des virgules de divers types de médias, par exemple "text/html,text/xhtml+xml,...", mais pour notre exemple, nous garderons les choses simples. Soyez indulgent, d’accord ?)

Voici la requête HTTP envoyée au serveur Web :

				
					> GET /books/9780780797086 HTTP/1.1
> Host: my-site.org
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ...
> Accept: text/html
				
			

Dans la mesure de ce qui a été dit, le serveur inspecte l’en-tête Accept pour servir la représentation de la ressource demandée et voici sa réponse :

				
					< HTTP/1.1 303 See Other
< Server: nginx/1.21.0
< Date: Wed, 07 Jul 2021 17:29:08 GMT
< Content-Type: text/html
< Content-Length: 216
< Location: https://my-site/pages/books/9780780797086
< Connection: keep-alive
< Accept: text/html
				
			

Veuillez noter que l’URI demandée et l’URI de la destination identifient le livre en tant que ressource. Cela répond à l’exigence selon laquelle l’URI doit identifier la ressource et être sans ambiguïté. L’URI cible contient un segment /pages/. Cela nous permet de comprendre que la ressource est une page Web.

Je sais, je sais, je vous entends presque vous plaindre : et le SEO ? Les moteurs de recherche, et les gens aussi, ne se soucient pas beaucoup des codes numériques ; ils s’attendent à avoir des informations intelligibles dans les URIs, suffisamment expressives pour être indexées et mémorisées.

Vous avez raison.

Mais comment pourrions-nous convaincre le serveur Web, qui par nature ignore l’existence d’une base de données derrière tout cela, de résoudre l’ID en une URI plus significative pour les humains et les moteurs de recherche et de rediriger vers cette URI ?

La tâche peut être facilement abordée en transférant la requête initiale vers un bloc d’application (Node, PHP, Java, peu importe) qui peut résoudre l’ID de la ressource en un modèle d’URI significatif.

Cette tâche peut également être effectuée par le client, ayant accès, par exemple, à l’API RESTful pour cette ressource et effectuant une transformation de l’URI suivie d’une redirection.

Dans un tel cas, voici comment notre réponse changerait :

				
					< HTTP/1.1 303 See Other
< Server: nginx/1.21.0
< Date: Wed, 07 Jul 2021 17:31:08 GMT
< Content-Type: text/html
< Content-Length: 261
< Location: https://my-site/pages/books/harry-potter-and-the-philosophers-stone-isbn-9780780797086
< Connection: keep-alive
< Accept: text/html
				
			

Exemple Cas #2 : JSON

Dans ce cas, notre client est une machine. L’en-tête Accept est défini sur application/json. Voici la requête :

				
					> GET /books/9780780797086 HTTP/1.1
> Host: my-site.org
> User-Agent: insomnia/2021.4.0
> Accept: application/json
				
			

et la réponse :

				
					< HTTP/1.1 303 See Other
< Server: nginx/1.21.0
< Date: Wed, 07 Jul 2021 17:29:54 GMT
< Content-Type: application/json
< Content-Length: 229
< Location: https://my-site/data/books/9780780797086
< Connection: keep-alive
< Accept: application/json
				
			

Comme vous pouvez le voir, le segment /pages/ dans l’URI a été remplacé par /data/. Nous configurerons le serveur Web pour que la requête soit transférée à notre serveur d’application RESTful.

De cette manière, le client recevra une description JSON de la ressource.

Exemple Cas #3 : RDF

Ce cas ne diffère pas beaucoup du précédent, la principale différence réside dans le fait que l’URI cible sera traitée par un magasin RDF au lieu de notre serveur d’application RESTful.

				
					> GET /books/9780780797086 HTTP/1.1
> Host: my-site.org
> User-Agent: insomnia/2021.4.0
> Accept: application/rdf+xml
				
			
				
					< HTTP/1.1 303 See Other
< Server: nginx/1.21.0
< Date: Wed, 07 Jul 2021 17:40:21 GMT
< Content-Type: application/rdf+xml
< Content-Length: 235
< Location: https://my-site/data/books/9780780797086
< Connection: keep-alive
< Accept: application/rdf+xml
				
			

Quoi ? L’URI cible est la même que celle de l’exemple précédent (JSON) ! Comment est-ce possible ?

C’est simple : remarquez que la réponse contient également un en-tête Accept, nous transmettons donc explicitement les informations sur le format nécessaire à l’URI cible. Ce sera à elle de diriger la requête selon l’en-tête Accept.

Doit-on faire tout cela à chaque fois ?

Sur le Web Sémantique, les choses sont simplifiées pour que les clients (qu’ils soient humains ou machines) puissent obtenir une description de la ressource nécessaire dans le format requis. Et cette accessibilité est maintenue. Néanmoins, un client peut même choisir de pointer directement vers l’URI dont il a besoin sans utiliser celle générique ; il pourrait, par exemple, décider de pointer directement vers le segment URI /data/ ou /rdf/, en fournissant toujours un en-tête Accept cohérent.

Cela dit, cela peut être considéré comme une approche déconseillée. L’URI générique frontale pour une certaine ressource est là pour éviter toute mauvaise direction des clients en vue de changements futurs. Les segments /data/ ou /pages/ pourraient ne plus être présents à un moment donné à cause d’une réorganisation ou d’un refactoring des ressources.

La seule chose qui ne devrait pas changer face au monde serait l’URI frontale pour cette ressource.

Cela garantira le meilleur résultat de récupération de la ressource pour les clients utilisant nos services.

Et la performance ?

En considérant toute l’évaluation des requêtes, les étapes de redirection, etc., on pourrait argumenter que la performance est un problème. En effet, un certain surcoût pourrait être présent pour tout le trajet aller-retour, mais ce design – qui se concentre sur la récupération des ressources pour les humains et les machines – nécessite des solutions HTTP de proxy inverse efficaces et évolutives.

D’après mon expérience personnelle, j’ai obtenu de très bons résultats en utilisant Nginx, un proxy inverse HTTP qui offre des performances exceptionnelles. Néanmoins, la majeure partie de cette direction repose sur votre configuration.

Voici trois lignes directrices à garder à l’esprit :

  • Gardez les choses aussi simples que possible, c’est-à-dire minimisez le nombre d’étapes d’évaluation/de redirection/de proxy effectuées par votre proxy inverse.
  • Utilisez la meilleure solution possible ; Nginx est très bon, mais essayez d’autres solutions par vous-même.
  • Maximisez les performances de toutes les parties mobiles dans votre architecture de service (serveur web, base de données, serveur d’applications, magasin RDF), en prêtant attention à la latence réseau (par exemple, positionner toutes les machines/appareils dans le même réseau privé peut être d’une grande aide).

Conclusions

Nous avons examiné comment le protocole HTTP est idéal pour les objectifs du Web Sémantique, et comment les dynamiques de redirection 303 fonctionnent au niveau du protocole.

Dans les prochaines parties, nous examinerons comment configurer le proxy inverse pour effectuer le transfert d’URI et comment réduire la surcharge de tout le processus.

Restez à l’écoute pour de nouveaux articles de SpazioCodice !

Share this post

Laisser un commentaire

En savoir plus sur SpazioCodice

Abonnez-vous pour poursuivre la lecture et avoir accès à l’ensemble des archives.

Poursuivre la lecture