117 votes

Qu'est-ce qui est valide et qu'est-ce qui ne l'est pas dans une requête URI ?

Contexte (question plus bas)

J'ai fait des recherches sur Google en lisant les RFC et les questions de l'OS pour essayer de résoudre ce problème, mais je n'ai toujours rien compris.

Je suppose donc que nous votons pour la "meilleure" réponse et que c'est tout, ou bien ?

En gros, cela se résume à ceci.

3.4. Composant de requête

La composante "requête" est une chaîne d'informations à interpréter par la ressource.

query = *uric

Dans un composant de requête, les caractères " ;", "/", " ?", " :", "@", "&", "=", "+", "," et "$" sont réservés.

La première chose qui m'étonne est que *uric est défini comme suit

uric = reserved | unreserved | escaped

reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","

Ce point est toutefois quelque peu clarifié par des paragraphes tels que

La classe syntaxique "réservée" ci-dessus fait référence aux caractères qui sont autorisés dans un URI, mais qui peuvent ne pas être autorisés dans un composant particulier de la syntaxe générique de l'URI ; ils sont utilisés comme délimiteurs des composants décrits à la section 3.

Les caractères de l'ensemble "réservé" ne sont pas réservés dans tous les contextes. L'ensemble des caractères effectivement réservés dans un composant URI donné est défini par ce composant. En général, un caractère est réservé si la sémantique de l'URI change si le caractère est remplacé par son codage US-ASCII échappé.

Ce dernier extrait semble quelque peu rétrograde, mais il indique clairement que le jeu de caractères réservés dépend du contexte. Pourtant, le paragraphe 3.4 indique que tous les caractères réservés sont réservés dans un composant de requête, mais la seule chose qui changerait la sémantique ici est l'échappement du point d'interrogation ( ?), car les URI ne définissent pas le concept de chaîne de requête.

À ce stade, j'ai complètement abandonné les RFC, mais j'ai trouvé le RFC 1738 particulièrement intéressant.

Une URL HTTP se présente sous la forme suivante :

http://<host>:<port>/<path>?<searchpart>

Dans les composants <path> et <searchpart>, les caractères "/", " ;", " ?" sont réservés. Le caractère "/" peut être utilisé dans HTTP pour désigner une structure hiérarchique.

J'interprète cela, au moins en ce qui concerne les URL HTTP, comme le fait que le RFC 1738 remplace le RFC 2396. Comme la requête URI n'a pas de notion de chaîne de requête, l'interprétation de reserved ne me permet pas vraiment de définir des chaînes de requête comme j'ai l'habitude de le faire maintenant.

Question

Tout a commencé lorsque j'ai voulu transmettre une liste de nombres avec la demande d'une autre ressource. Je n'y ai pas réfléchi et je l'ai simplement transmise sous forme de valeurs séparées par des virgules. À ma grande surprise, la virgule a été échappée. La requête page.html?q=1,2,3 codé transformé en page.html?q=1%2C2%2C3 ça marche, mais c'est moche et je ne m'y attendais pas. C'est alors que j'ai commencé à parcourir les RFC.

Ma première question est la suivante : est-il vraiment nécessaire d'encoder les virgules ?

Ma réponse, selon le RFC 2396 : oui, selon le RFC 1738 : non

Plus tard, j'ai trouvé des messages relatifs à la transmission de listes entre les requêtes. L'approche csv était considérée comme mauvaise. Ceci est apparu à la place (je n'ai jamais vu cela auparavant).

page.html?q=1;q=2;q=3

Ma deuxième question est la suivante : s'agit-il d'une URL valide ?

Ma réponse, selon le RFC 2396 : non, selon le RFC 1738 : non ( ; est réservé)

Je n'ai aucun problème à passer du csv tant qu'il s'agit de nombres, mais il est vrai que l'on court le risque de devoir encoder et décoder les valeurs dans les deux sens si la virgule est soudainement nécessaire pour autre chose. Quoi qu'il en soit, j'ai essayé le truc de la chaîne de requête avec point-virgule en ASP.NET et le résultat n'était pas celui que j'attendais.

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Je ne vois pas en quoi cela diffère grandement d'une approche csv, car lorsque je demande "a", j'obtiens une chaîne de caractères avec des virgules. ASP.NET n'est certainement pas une implémentation de référence, mais il ne m'a pas encore laissé tomber.

Mais surtout, et c'est ma troisième question, où se trouvent les spécifications et que feriez-vous ou ne feriez-vous pas ?

82voto

outis Points 39377

Le fait qu'un caractère soit réservé dans un composant URL générique ne signifie pas qu'il doive être échappé lorsqu'il apparaît dans le composant ou dans les données qu'il contient. Le caractère doit également être défini comme délimiteur dans la syntaxe générique ou spécifique au schéma et l'apparition du caractère doit se faire dans les données.

La norme actuelle pour les URI génériques est la suivante RFC 3986 qui s'exprime ainsi :

2.2. Caractères réservés

Les URI comprennent des composants et des sous-composants délimités par des caractères de l'ensemble "réservé". Ces caractères sont dits "réservés" parce qu'ils peuvent (ou non) être définis comme délimiteurs par la syntaxe générique, par la syntaxe spécifique à chaque schéma ou par la syntaxe spécifique à l'implémentation de l'algorithme de déréférencement d'un URI. Si les données d'un composant URI conflit avec l'objectif d'un caractère réservé en tant que délimiteur [Les données contradictoires doivent alors être codées en pourcentage avant que l'URI ne soit formé.

   reserved    = gen-delims / sub-delims

gen-delims  = ":" / "/" / "?" / "#" / "\[" / "\]" / "@"

sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
/ "\*" / "+" / "," / ";" / "="

3.3. Composant du chemin d'accès

[...] pchar = unreserved / pct-encoded / sub-delims / ":" / "@"[...]

3.4 Composant d'interrogation

[...] query = *( pchar / "/" / "?" )

Les virgules sont donc explicitement autorisées dans les chaînes de requête et ne doivent être échappées dans les données que si des schémas spécifiques les définissent comme délimiteurs. Le schéma HTTP n'utilise pas la virgule ou le point-virgule comme délimiteur dans les chaînes de requête, et il n'est donc pas nécessaire de les échapper. La question de savoir si les navigateurs respectent cette norme est une autre question.

L'utilisation de CSV devrait fonctionner correctement pour les données de type chaîne, il suffit de suivre les conventions CSV standard et de mettre les données entre guillemets ou d'échapper aux virgules par des barres obliques inverses.

Quant à la RFC 2396, elle autorise également les virgules non encapsulées dans les chaînes de requête HTTP :

2.2. Caractères réservés

De nombreux URI comprennent des composants constitués ou délimités par certains caractères spéciaux. Ces caractères sont dits "réservés", car leur utilisation dans le composant URI est limitée à l'usage qui leur est réservé. réservé. Si les données d'un composant de l'URI entrent en conflit avec l'usage réservé, les données conflictuelles doivent être supprimées. l'objet réservé, les données conflictuelles doivent être échappées avant de avant de former l'URI.

Comme les virgules n'ont pas d'usage réservé dans le cadre du protocole HTTP, elles ne doivent pas être échappées dans les données. La remarque du § 2.3 concernant les caractères réservés qui changent de sémantique lorsqu'ils sont codés en pourcentage ne s'applique que de manière générale ; les caractères peuvent être codés en pourcentage sans changer de sémantique pour des schémas spécifiques, tout en restant réservés.

11voto

Nas Banov Points 7293

Il suffit d'utiliser ?q=1+2+3

Je réponds ici à une quatrième question :) qui n'a pas été posée mais qui a commencé par : comment passer une liste de nombres à la manière des valeurs séparées par des virgules ? Il me semble que la meilleure approche est de les passer séparés par des espaces, où les espaces seront encodés en url-form-encodage à + . Cela fonctionne très bien, tant que vous savez que les valeurs de la liste ne contiennent pas d'espaces (ce que les nombres ont tendance à ne pas faire).

7voto

bobince Points 270740

page.html?q=1;q=2;q=3

S'agit-il d'une URL valide ?

Oui. ; est réservé, mais pas par un RFC. Le contexte qui définit ce composant est la définition de l'élément application/x-www-form-urlencoded qui fait partie de la norme HTML (section 17.13.4.1 ). En particulier, la note furtive cachée dans la section B.2.2 :

Nous recommandons aux implémenteurs de serveurs HTTP, et en particulier aux implémenteurs de CGI, d'accepter l'utilisation de " ;" à la place de "&" pour éviter aux auteurs d'avoir à escamoter les caractères "&" de cette manière.

Malheureusement, de nombreux frameworks de script côté serveur, dont ASP.NET, ne prennent pas en charge cette utilisation.

1voto

ErikE Points 18233

Je tiens à souligner que page.html?q=1&q=2&q=3 est également une url valide. Il s'agit d'une manière tout à fait légitime d'exprimer un tableau dans une chaîne de requête. La technologie de votre serveur déterminera la manière exacte dont cela est présenté.

En ASP classique, vous vérifiez Response.QueryString("q").Count et utiliser ensuite Response.QueryString("q")(0) (et (1) et (2)).

Notez que vous avez vu cela dans votre ASP.NET, aussi (je pense que ce n'était pas voulu, mais regardez) :

Default.aspx?a=1;a=2&b=1&a=3

Request.QueryString["a"] = "1;a=2,3"
Request.QueryString["b"] = "1"

Remarquez que le point-virgule n'est pas pris en compte, ce qui donne a défini deux fois, et vous avez obtenu sa valeur deux fois, séparées par une virgule. Utilisation de toutes les esperluettes Default.aspx?a=1&a=2&b=1&a=3 produira a comme "1,2,3". Mais je suis sûr qu'il existe une méthode pour obtenir chaque élément individuel, dans le cas où les éléments eux-mêmes contiennent des virgules. Il s'agit simplement de la propriété par défaut de la chaîne de requête non indexée qui concatène les sous-valeurs avec des séparateurs de virgules.

1voto

slash Points 36

J'ai eu le même problème. L'URL qui était hyperliée était une URL tierce et attendait une liste de paramètres au format page.html?q=1,2,3 UNIQUEMENT et l'URL page.html?q=1%2C2%2C3 n'a pas fonctionné. J'ai réussi à le faire fonctionner en utilisant le javascript. Ce n'est peut-être pas la meilleure approche, mais je peux vérifier la solution. aquí si cela peut aider quelqu'un.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X