2009-11-17 8 views
104

Tengo problemas en la búsqueda de información autorizada sobre el comportamiento con HTTP GET cadena de consulta campos duplicados, comoposición de autoridad de las llaves de consulta GET HTTP duplicados

http://example.com/page?field=foo&field=bar 

y, en particular, si la orden se mantiene o no. La mayoría de los lenguajes orientados a web producen una matriz que contiene foo y barra asociados a un "campo" clave, pero me gustaría saber si existe una declaración autorizada (por ejemplo, en un RFC) sobre este punto. RFC 3986 tiene una sección 3.4. Query, que se refiere a pares clave = valor, pero no se dice nada sobre cómo interpretar el orden y duplicar campos, etc. Esto tiene sentido, ya que depende del back-end, y no del alcance de ese RFC ...

Aunque existe un estándar de facto, me gustaría ver una fuente autorizada para él, solo por curiosidad.

+0

También me he estado preguntando sobre eso. La otra cosa es la especificación sobre la fusión de los parámetros de la cadena de consulta con aquellos en el cuerpo POST. – Thilo

+0

En el rancho de código, la gente dice que no hay garantía de pedido. Pero ese hilo es antiguo y nadie lo respalda de ninguna manera: http://www.coderanch.com/t/357197/Servlets/java/getParameterValues-order – Thilo

+1

Además del servidor que mantiene el orden de la cadena de consulta, también está la cuestión de si el navegador los envía en DOM (u otro orden fijo). – Thilo

Respuesta

82

No es ninguna especificación en esto. Puedes hacer lo que quieras.

Los enfoques típicos incluyen: first-given, last-given, array-of-all, string-join-with-comma-of-all.

Supongamos que la solicitud de prima es:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1 
Host: example.com 

Luego hay varias opciones para lo request.query['tag'] debería producir, en función del idioma o del marco:

request.query['tag'] => 'ruby' 
request.query['tag'] => 'rails' 
request.query['tag'] => ['ruby', 'rails'] 
request.query['tag'] => 'ruby,rails' 
+8

Más al punto de la pregunta, también existe la opción de ['rails', 'ruby'] (orden diferente). – Thilo

+1

Uno ciertamente puede hacer una gran cantidad de cosas. – yfeldblum

+6

.NET le dará como una matriz (no me importó el orden cuando lo probé), PHP siempre le dará la última y Java (al menos el sistema con el que trabaje basado en Java) siempre será el primer valor. http://stackoverflow.com/questions/1809494/post-the-checkboxes-that-are-unchecked/8972025#8972025 – SimonSimCity

3

Típicamente, los valores de parámetros duplicados como

http://example.com/page?field=foo&field=bar 

resultado en un único parámetro queryString que es una matriz:

field[0]=='foo' 
field[1]=='bar' 

he visto este comportamiento en ASP, ASP.NET y PHP4.

+0

exactamente, este es el estándar de facto, pero por lo que veo no hay una decisión autorizada al respecto. Como no creo que este sea el caso, simplemente soy inepto para encontrarlo. –

+1

Sí, probablemente todos hayan visto ese comportamiento. La pregunta era si eso está realmente especificado en alguna parte. – Thilo

4

La mayoría (¿todos?) De los marcos no ofrecen garantías, por lo que supongamos que se devolverán en orden aleatorio.

Siempre adopte el enfoque más seguro.

Por ejemplo, java HttpServlet interfaz: (. Del orden de un iterador de java.util.Map no se puede confiar en cualquiera) ServletRequest.html#getParameterValues

Incluso el método getParameterMap deja fuera cualquier mención sobre el orden parámetro

12

puedo confirmar que para PHP (al menos en la versión 4.4.4 y posteriores) funciona así:

GET /blog/posts?tag=ruby&tag=rails HTTP/1.1 
Host: example.com 

resultados en:

request.query['tag'] => 'rails' 

Pero

GET /blog/posts?tag[]=ruby&tag[]=rails HTTP/1.1 
Host: example.com 

resultados en:

request.query['tag'] => ['ruby', 'rails'] 

Este comportamiento es el mismo para GET y POST datos.

+1

El sufijo '[]' parece un comportamiento realmente extraño, pero si intentas enviar un Array como argumento a través de '.ajax()' de jQuery, entonces los agregará automáticamente de la misma manera. Parece que esto beneficia a los usuarios de PHP. –

+4

@IanClark Es intuitivo para los programadores de PHP: en PHP simple, '$ foo [] = 1' se agrega a una matriz. Django (Python) también hace lo mismo. – Izkata

4

La respuesta de yfeldblum es perfecta.

Sólo una nota sobre una quinta comportamiento Noté recientemente: en Windows Phone, la apertura de una aplicación con una URI con una clave de consulta duplicado dará lugar a NavigationFailed con:

System.ArgumentException: Un artículo con la misma clave ya se ha agregado.

El culpable es System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Así que el sistema ni siquiera le permitirá manejarlo de la manera que desee, lo prohibirá. Te queda la única solución para elegir tu propio formato (CSV, JSON, XML, ...) y uri-escape-it.

+1

Parece una falla interna de esa función, en lugar de una opción de diseño. La función probable no verifica si hay claves duplicadas en el diccionario que está creando. Los diccionarios, por supuesto, requieren claves únicas. – gligoran

0

Tenía la misma pregunta. Estoy escribiendo la función de Javascript para analizar y codificar las consultas. No sé si una cadena de consulta tiene nombres duplicados o un nombre con corchetes, como x [] = 1 & x [] = 2, es estándar aunque algunos idiomas admiten este formato.

Pero me parece que Chrome y Firefox tienen una nueva clase llamada URLSeachParams y solo admite el formato más simple como name=value. Si hay nombres duplicados en la cadena de consulta, el método get de URLSearchParams solo devuelve el primero.

Así que personalmente, tal vez una url de nombres duplicados y más simple es mucho más segura para el futuro.

+0

* Si hay nombres duplicados en la cadena de consulta, el método get de URLSearchParams solo devuelve el primero. * Esto no es correcto: puede recuperar todos los valores como una matriz usando ['URLSearchParams.getAll ('x')'] (https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/getAll) – Blaise

Cuestiones relacionadas