Posizione autorevole di chiavi di query HTTP GET duplicate


137

Sto riscontrando problemi nel trovare informazioni autorevoli sul comportamento con campi duplicati della stringa di query HTTP GET, come

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

e in particolare se l'ordine è mantenuto o meno. La maggior parte dei linguaggi orientati al web producono un array contenente sia foo che bar associati a un "campo" chiave, ma vorrei sapere se esistono dichiarazioni autorevoli (ad esempio su un RFC) su questo punto. RFC 3986 ha una sezione 3.4. Query, che fa riferimento a coppie chiave = valore, ma non si dice nulla su come interpretare i campi di ordine e duplicazione e così via. Questo ha senso, poiché dipende dal backend e non rientra nell'ambito di tale RFC ...

Sebbene esista uno standard di fatto, mi piacerebbe vedere una fonte autorevole per esso, solo per curiosità.


Mi stavo chiedendo anche questo. L'altra cosa sono le specifiche sull'unione dei parametri dalla stringa di query con quelli nel corpo POST.
Thilo,

Al ranch di codice, la gente dice che non esiste una garanzia d'ordine. Ma quel thread è vecchio e nessuno ne fa il backup in alcun modo: coderanch.com/t/357197/Servlets/java/getParameterValues-order
Thilo

1
Oltre al server che mantiene l'ordine della stringa di query, c'è anche la domanda sul browser che li invia in ordine DOM (o qualche altro fisso).
Thilo,

Risposte:


112

Non ci sono specifiche al riguardo. Puoi fare quello che ti piace.

Gli approcci tipici includono: primo dato, ultimo dato, array-of-all, string-join-with-comma-of-all.

Supponiamo che la richiesta non elaborata sia:

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

Quindi ci sono varie opzioni per ciò che request.query['tag']dovrebbe produrre, a seconda della lingua o del framework:

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

12
Più al punto della domanda, c'è anche l'opzione di ['rails', 'ruby'] (ordine diverso).
Thilo,

2
Si può certamente fare un gran numero di cose.
yfeldblum,

7
.NET ti fornirà come un array (non mi sono preoccupato dell'ordine quando l'ho provato), PHP ti darà sempre l'ultimo e Java (almeno il sistema con cui ho lavorato basato su Java) sempre il primo valore. stackoverflow.com/questions/1809494/...
SimonSimCity

17
Questo si basa su un attacco chiamato HTTP Parameter Pollution ed è stato analizzato da OWASP: owasp.org/images/b/ba/AppsecEU09_CarettoniDiPaola_v0.8.pdf A pagina 9 troverai un elenco di 20 sistemi e una descrizione su come gestiscono questa edizione.
SimonSimCity,

1
@SimonSimCity oltre a ciò, PHP creerà effettivamente un array se aggiungi parentesi quadre con un indice opzionale al nome del parametro.
Martin Ender

14

Posso confermare che per PHP (almeno nella versione 4.4.4 e successive) funziona così:

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

risulta in:

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

Ma

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

risulta in:

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

Questo comportamento è lo stesso per i dati GET e POST.


1
Il []suffisso sembra un comportamento davvero strano, ma se provi a inviare un array come argomento tramite jQuery .ajax(), li aggiungerà automaticamente per te allo stesso modo. Sembra che questo sia a beneficio degli utenti di PHP.
Ian Clark,

4
@IanClark È intuitivo per i programmatori PHP - in semplice PHP, si $foo[] = 1aggiunge a un array. Anche Django (Python) fa la stessa cosa.
Izkata,

Può verificare su Apache Tomcat restituisce stringhe concatenate da virgola.
Gaurav Ojha

8

la risposta di yfeldblum è perfetta.

Solo una nota su un quinto comportamento che ho notato di recente: su Windows Phone , l'apertura di un'applicazione con un uri con una chiave di query duplicata comporterà NavigationFailed con:

System.ArgumentException: un elemento con la stessa chiave era già stato aggiunto.

Il colpevole è System.Windows.Navigation.UriParsingHelper.InternalUriParseQueryStringToDictionary(Uri uri, Boolean decodeResults).

Quindi il sistema non ti permetterà nemmeno di gestirlo nel modo desiderato, lo proibirà. Ti resta l'unica soluzione per scegliere il tuo formato (CSV, JSON, XML, ...) e uri-escape-it.


2
Sembra un bug interno di quella funzione, piuttosto che una scelta progettuale. La funzione probabilmente non controlla la presenza di chiavi duplicate nel dizionario che sta creando. I dizionari, ovviamente, richiedono chiavi uniche.
Gligoran

1
Quindi il browser client , non il server, sta generando un errore in questa situazione? Sembra un bug. Mi chiedo se questo bug esiste ancora oggi?
Jon Schneider,

1
@JonSchneider Sì, il client lancia NavigationFailedquesto URI. Ma, scusami, ho abbandonato lo sviluppo di Windows (Phone) un mese dopo questo post e sono passato a macOS (iOS), quindi al giorno d'oggi non posso più fare a meno per tenere traccia di questo problema.
Cœur,

5

La maggior parte (tutti?) Dei framework non offre garanzie, quindi supponiamo che verranno restituiti in ordine casuale.

Adottare sempre l'approccio più sicuro.

Ad esempio, interfaccia Java HttpServlet: ServletRequest.html # getParameterValues

Perfino il metodo getParameterMap tralascia qualsiasi menzione sull'ordine dei parametri (neanche un ordine di un iteratore java.util.Map).


3

In genere, valori di parametro duplicati come

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

risulta in un singolo parametro queryString che è un array:

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

Ho visto questo comportamento in ASP, ASP.NET e PHP4.


esattamente, questo è lo standard di fatto, ma per quanto vedo non vi è alcuna decisione autorevole al riguardo. Dal momento che non credo che sia così, non sono in grado di trovarlo.
Stefano Borini,

2
Sì, probabilmente tutti hanno visto quel comportamento. La domanda era se questo è effettivamente specificato da qualche parte.
Thilo,

-1

Ho avuto la stessa domanda. Sto scrivendo la funzione JavaScript per analizzare e stringere le query. Non so se una stringa di query abbia nomi duplicati o nome tra parentesi, come x [] = 1 & x [] = 2, è standard sebbene alcune lingue supportino questo formato.

Ma trovo che Chrome e Firefox abbiano una nuova classe denominata URLSeachParamse supporta solo il formato più semplice come name=value. Se nella stringa di query sono presenti nomi duplicati, il getmetodo diURLSearchParams restituisce solo il primo.

Quindi personalmente, forse l'URL di un nome più semplice e senza duplicati è molto più sicuro per il futuro.


1
Se nella stringa di query sono presenti nomi duplicati, il metodo get di URLSearchParams restituisce solo il primo. Questo non è corretto: puoi recuperare tutto il valore come un array usandoURLSearchParams.getAll('x')
Blaise il

@ Blaise Grazie mille, ho frainteso la funzione prima.
LCB
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.