Contexte (question plus bas)
J'ai fait des recherches sur Google en lisant des RFC et des questions SO pour essayer de résoudre ce problème, mais je n'ai toujours pas de prise.
Donc je suppose que nous votons simplement pour la "meilleure" réponse et c'est tout, ou?
Fondamentalement, cela se résume à ceci.
3.4. Composant de requête
Le composant de 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 me déroute est que * uric est défini comme ceci
uric = reserved | unreserved | escaped
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Ceci est cependant quelque peu clarifié par des paragraphes tels que
La classe de syntaxe «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 URI générique; ils sont utilisés comme délimiteurs des composants décrits dans 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 réellement 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 encodage US-ASCII échappé.
Ce dernier extrait semble quelque peu en arrière, mais il indique clairement que le jeu de caractères réservé dépend du contexte. Pourtant, 3.4 déclare que tous les caractères réservés sont réservés dans un composant de requête, cependant, la seule chose qui changerait la sémantique ici est d'échapper au 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é la RFC 1738 particulièrement intéressante.
Une URL HTTP prend la forme:
http://<host>:<port>/<path>?<searchpart>
Dans les composants <chemin> et <searchpart>, "/", ";", "?" 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 que la RFC 1738 remplace la RFC 2396. Parce que la requête URI n'a aucune notion de chaîne de requête, l'interprétation de réservé ne me permet pas vraiment de définir des chaînes de requête comme je suis habitué à faire maintenant.
Question
Tout cela a commencé lorsque j'ai voulu transmettre une liste de nombres avec la demande d'une autre ressource. Je n'y ai pas beaucoup réfléchi et je l'ai juste passé sous forme de valeurs séparées par des virgules. À ma grande surprise, la virgule s'est échappée. La requête page.html?q=1,2,3
encodée en page.html?q=1%2C2%2C3
elle fonctionne, mais elle est moche et ne s'y attendait pas. C'est là que j'ai commencé à passer par les RFC.
Ma première question est simplement: est-ce que l'encodage des virgules est vraiment nécessaire?
Ma réponse, selon RFC 2396: oui, selon RFC 1738: non
Plus tard, j'ai trouvé des articles liés au passage de listes entre les demandes. Où l'approche CSV était sur le point d'être mauvaise. Cela est apparu à la place, (je n'ai jamais vu cela auparavant).
page.html?q=1;q=2;q=3
Ma deuxième question, est-ce une URL valide?
Ma réponse, selon RFC 2396: non, selon RFC 1738: non (; est réservé)
Je n'ai aucun problème avec le passage de csv tant qu'il s'agit de nombres, mais oui, vous courez le risque d'avoir à encoder et décoder des valeurs d'avant en arrière si la virgule est soudainement nécessaire pour autre chose. Quoi qu'il en soit, j'ai essayé la chaîne de requête point-virgule avec ASP.NET et le résultat n'était pas ce à quoi je m'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 avec des virgules. ASP.NET n'est certainement pas une implémentation de référence, mais cela ne m'a pas encore laissé tomber.
Mais le plus important - ma troisième question - où est la spécification pour cela? et que feriez-vous ou d'ailleurs ne pas faire?
la source
Réponses:
Le fait qu'un caractère soit réservé dans un composant URL générique ne signifie pas qu'il doit être échappé lorsqu'il apparaît dans le composant ou dans les données du composant. Le caractère doit également être défini comme un délimiteur dans la syntaxe générique ou spécifique au schéma et l'apparence du caractère doit être dans les données.
La norme actuelle pour les URI génériques est la RFC 3986 , qui a ceci à dire:
Ainsi, les virgules sont 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 le définissent comme un délimiteur. Le schéma HTTP n'utilise pas la virgule ou le point-virgule comme délimiteur dans les chaînes de requête, il n'est donc pas nécessaire de les échapper. Que les navigateurs respectent cette norme est une autre affaire.
L'utilisation de CSV devrait fonctionner correctement pour les données de type chaîne, il vous suffit de suivre les conventions CSV standard et de citer les données ou d'échapper les virgules avec des barres obliques inverses.
Quant à la RFC 2396, elle autorise également les virgules sans échappement dans les chaînes de requête HTTP:
Étant donné que les virgules n'ont pas de but réservé dans le schéma HTTP, elles ne doivent pas être échappées dans les données. La note du § 2.3 sur les caractères réservés étant ceux qui changent de sémantique lorsqu'ils sont codés en pourcentage ne s'applique qu'en général; les caractères peuvent être codés en pourcentage sans changer la sémantique pour des schémas spécifiques et pourtant être réservés.
la source
Pour répondre à ce qui est valide dans une chaîne de requête, j'ai vérifié quels caractères spéciaux sont remplacés par chrome lors d'une demande:
Remarque: cela ne signifie probablement pas que vous ne devriez pas échapper les caractères qui n'ont pas été remplacés lorsque vous générez des URI pour les liens. Par exemple, il est souvent recommandé de ne pas utiliser
~
dans les URI en raison de problèmes de compatibilité, mais c'est toujours un caractère valide.Un autre exemple serait le signe plus qui est valide mais généralement traité comme un blanc encodé lorsqu'un serveur le reçoit dans le cadre d'une requête. Ainsi, il doit être encodé même s'il est valide lorsque son but est de représenter un plus et non un espace.
Donc, pour répondre à ce qui doit être encodé: Caractères invalides et caractères que vous souhaitez traiter littéralement mais qui ont une signification particulière ou peuvent causer des problèmes au niveau du serveur.
la source
/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b#1;c#2
qu'un paramètre de requête valide?#
il ne peut pas apparaître dans la partie requête d'un URI tel quel . Vous devrez l'encoder en tant que%23
, de sorte que l'URI devrait être/programming/2366260/whats-valid-and-whats-not-in-a-uri-query?param=b%231;c%232
.Juste utiliser
?q=1+2+3
Je réponds ici à une quatrième question :) qui n'a pas demandé mais tout a commencé par: comment transmettre une liste de nombres séparés par des virgules? Il me semble que la meilleure approche est simplement de les passer séparés par des espaces, où les espaces seront encodés sous forme d'URL
+
. 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).la source
+
est encore plus logique dans le cas précis où je cherchais à utiliser une virgule.Oui. Le
;
est réservé, mais pas par un RFC. Le contexte qui définit ce composant est la définition duapplication/x-www-form-urlencoded
type de média, qui fait partie du standard HTML (section 17.13.4.1 ). En particulier la note sournoise cachée dans la section B.2.2 :Malheureusement, de nombreux frameworks de script côté serveur populaires, y compris ASP.NET, ne prennent pas en charge cette utilisation.
la source
?q=1;q=2;q=3
requête soit valide, elle est ambiguë: certains frameworks côté serveur la liront comme signifiant{ q: '1;q=2;q=3' }
, d'autres peuvent le faire comme{ q: {'1', '2', '3'}}
.;
, ce qui signifie que HTML4 et HTML5 sont incohérents. Ugh, les dangers du langage non normatif dans un document de spécification ...{ q: 3 }
Je voudrais noter qu'il
page.html?q=1&q=2&q=3
s'agit également d'une URL valide. C'est 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 comment exactement cela est présenté.Dans ASP classique, vous vérifiez
Response.QueryString("q").Count
, puis utilisezResponse.QueryString("q")(0)
(et (1) et (2)).Notez que vous avez également vu cela dans votre ASP.NET (je pense que ce n'était pas prévu, mais regardez):
Notez que le point-virgule est ignoré, donc vous avez
a
défini deux fois et vous avez obtenu sa valeur deux fois, séparés par une virgule. L'utilisation de toutes les esperluettesDefault.aspx?a=1&a=2&b=1&a=3
donneraa
"1,2,3". Mais je suis sûr qu'il existe une méthode pour obtenir chaque élément individuel, au cas où les éléments eux-mêmes contiennent des virgules. C'est simplement la propriété par défaut de la QueryString non indexée qui concatène les sous-valeurs avec des séparateurs par virgule.la source
J'ai eu le même problème. L'URL contenant le lien hypertexte était une URL tierce et attendait une liste de paramètres au format
page.html?q=1,2,3
UNIQUEMENT et l'URLpage.html?q=1%2C2%2C3
ne fonctionnait pas. J'ai pu le faire fonctionner en utilisant javascript. Ce n'est peut-être pas la meilleure approche, mais vous pouvez consulter la solution ici si cela aide quelqu'un.la source
Si vous envoyez les caractères ENCODED dans un fichier FLASH / SWF , vous devez ENCODER le caractère deux fois !! (à cause de l'analyseur Flash)
la source