2010-11-17 7 views
65

Come indicato in http://www.boutell.com/newfaq/misc/urllength.html, la stringa di query HTTP ha una lunghezza limitata. Può essere limitato dal client (Firefox, IE, ...), dal server (Apache, IIS, ...) o dall'apparecchiatura di rete (firewall applicativo, ...).Come posso gestire i limiti di lunghezza della stringa di query HTTP GET e voglio comunque essere RESTful?

Oggi devo affrontare questo problema con un modulo di ricerca. Abbiamo sviluppato un modulo di ricerca con molti campi e questo modulo è stato inviato al server come richiesta GET, quindi posso aggiungere la pagina risultante ai segnalibri.

Abbiamo così tanti campi che la nostra stringa di query è lunga 1100 byte e abbiamo un firewall che elimina le richieste HTTP GET con più di 1024 byte. Il nostro amministratore di sistema ci consiglia di utilizzare il POST, quindi non ci saranno limiti.

Certo, il POST funzionerà, ma sento davvero una ricerca come GET e non un POST. Quindi penso che rivedrò i nostri nomi dei campi per assicurarmi che la stringa di query non sia troppo lunga, e se non posso essere pragmatico e usare POST.

Ma c'è un difetto nella progettazione dei servizi RESTful? Se abbiamo una lunghezza limitata nella richiesta GET, come posso fare per inviare oggetti di grandi dimensioni a un webservice RESTful? Ad esempio, se ho un programma che fa calcoli basati su un file, e voglio fornire un servizio web RESTful come questo: http://compute.com?content=<base64 file>. Questo non funzionerà perché la stringa di query non ha una lunghezza illimitata.

Sono un po 'perplesso ...

+2

Cosa significa "riposante" nei termini del tuo contesto? O parafrasando: perché GET è riposante e POST no? Perché GET può essere costruito usando una semplice concatenazione di stringhe? La limitazione della lunghezza della query consiste nell'evitare l'allocazione dinamica della memoria nelle app destinate a funzionare rapidamente. – khachik

+4

Quando voglio fare una ricerca, non voglio creare, eliminare o aggiornare qualcosa, voglio solo recuperare i dati, quindi non dovrei usare POST, DELETE o PUT, e dovrei usare GET.Questo è il modo in cui ho capito REST, ma potrei sbagliarmi a riguardo. – cbliard

+0

GET non è adatto per la ricerca, perché i risultati di una ricerca possono cambiare nel tempo. L'infrastruttura Web consente spesso il caching delle richieste GET. Se utilizzi GET rischi di ottenere risultati obsoleti per le ricerche. Il POST è il modo, come raccomandato di seguito. – occulus

risposta

45

In base alla descrizione, IMHO è necessario utilizzare un POST. POST è per mettere i dati sul server e, in alcuni casi, ottenere una risposta. Nel tuo caso, esegui una ricerca (invia una query al server) e ottieni il risultato di tale ricerca (recupera il risultato della query).

La definizione di GET indica che deve essere utilizzato per recuperare una risorsa già esistente. Per definizione, POST è quello di creare una nuova risorsa. Questo è esattamente quello che stai facendo: creare una risorsa sul server e recuperarla! Anche se non si memorizza il risultato della ricerca, è stato creato un oggetto sul server e recuperato. Come ha detto in precedenza PeterMmm, è possibile farlo con un POST (creare e memorizzare il risultato della query) e quindi utilizzare un GET per recuperare la query, ma è più pratico fare solo un POST e recuperare il risultato.

Spero che questo aiuti! :)

+2

Hai ragione, lo vedo come un POST perché la ricerca è una risorsa volatile appena calcolata. Ma ho ancora problemi nel vedere il confine tra POST e GET. Se voglio cercare tutti i libri di fantascienza in una biblioteca, otterrò una raccolta di risorse esistenti, quindi sono tentato di usare un GET, ma tu proponi di vederlo come un POST perché la ricerca è una nuova risorsa stessa. Pertanto, la stringa di query in GET deve essere utilizzata solo per modificare la rappresentazione dei dati, ma non per filtrare i dati. Ho ragione? – cbliard

+0

Sì, se si guarda dal punto di vista della ricerca, è una risorsa in sé che è necessario creare (fare un POST) per recuperare alcuni dati (un GET). Puoi vedere una ricerca come un nuovo oggetto istanziato da una raccolta di oggetti già esistenti! Usando l'esempio di libreria, hai i libri (risorse) sugli scaffali, ma vuoi solo una parte di essi e questa parte può essere vista come una nuova risorsa (pensa a un nuovo scaffale solo con i libri che cerchi). – jmpcm

+0

@jmpcm Per essere chiari, stai dicendo che qualsiasi parametro GET che sta semplicemente specificando quale risorsa esatta da ottenere (cioè '/? File = 123.txt') è l'unico modo corretto per usare GET e che POST dovrebbe essere usato per qualcosa di ricercato (cioè '/? file = *. txt'), o sto fraintendendo? – Patrick

5

resto è un modo di fare le cose, non è un protocollo. Anche se non ti piace il POST quando è davvero un GET, funzionerà.

Se si deve/deve rimanere con la definizione "standard" di GET, POST, ecc. Che forse considerare POST una query, quella query verrà archiviata sul server con un ID query e richiedere la query in un secondo momento con GET per id.

47

Specifica HTTP in realtà advises to use POST when sending data to a resource per il calcolo.

La ricerca sembra un calcolo, non una risorsa. Quello che potresti fare se vuoi che i tuoi risultati di ricerca siano una risorsa è creare un token per identificare quel risultato di ricerca specifico e reindirizzare l'agente utente a quella risorsa.

È quindi possibile eliminare i token dei risultati di ricerca dopo un certo periodo di tempo.

Esempio

POST /search 
query=something&category=c1&category=c2&... 

201 Created 
Location: /search/01543164876 

poi

GET /search/01543164876 

200 Ok 
... your results here... 

In questo modo, i browser e proxy può ancora nella cache dei risultati di ricerca, ma si sta presentando i parametri di query usando POST.

EDIT

Per chiarimenti, 01543164876 qui rappresenta un ID univoco per la risorsa che rappresenta la ricerca. Queste 2 richieste significano sostanzialmente: creare un nuovo oggetto di ricerca con questi criteri, quindi recuperare i risultati associati all'oggetto di ricerca creato.

Questo ID può essere un ID univoco generato per ogni nuova richiesta. Ciò significherebbe che il tuo server perderà oggetti di "ricerca" e dovrai pulirli regolarmente con una strategia di caching.

Oppure può essere un hash di tutti i criteri di ricerca che rappresentano effettivamente la ricerca richiesta dall'utente. Ciò consente di riutilizzare gli ID poiché ricreare una ricerca restituirà un ID esistente che potrebbe (o meno) essere già memorizzato nella cache.

+0

Come questo soddisfa il requisito OP relativo al bookmarking della query? – Rhubarb

+2

@Rubarub indirizza chiaramente creando una risorsa per una determinata ricerca. – maulik13

+2

Questo rallenterà i risultati. Esegui un post e quindi esegui un GET. aggiungerà almeno altri 300 ms per recuperare la ricerca. – jaxxbo

3

Per quanto riguarda il tuo esempio: http://compute.com?content={base64file}, userei il POST perché stai caricando "qualcosa" per essere calcolato. Per me questo "qualcosa" sembra più una risorsa come un parametro semplice.

Contrariamente a ciò nella ricerca normale, inizierei a seguire GET e parametri. È molto più facile per gli API-clients testare e giocare con la tua API. Rendi l'accesso di sola lettura (che nella maggior parte dei casi è la maggior parte del traffico) il più semplice possibile!

Ma il dilemma delle stringhe di query di grandi dimensioni è una limitazione valida di GET. Qui vorrei diventare pragmatico, finché non raggiungi questo limite vai con GET e url-params. Questo funzionerà nel 98% dei casi di ricerca. Agisci solo se raggiungi questo limite e poi introduci anche POST con payload (con mime-type Content-Type: application/x-www-form-urlencoded).

Hai altri esempi del mondo reale?

+0

Il calcolo era un esempio reale. Riguardo alla ricerca, vogliamo essere in grado di cercare transazioni su più punti vendita, quindi apriamo una nuova finestra del browser per selezionare i punti vendita. E quando convalidiamo modifichiamo un parametro nascosto nel modulo di ricerca per impostare i punti vendita selezionati. Se ce ne sono davvero molti, la richiesta di ricerca risultante avrà una stringa di query molto lunga. – cbliard

5

La confusione intorno a GET è una limitazione del browser. Se stai creando un'interfaccia RESTful per un'applicazione A2A o P2P, non c'è limite alla lunghezza del tuo GET.

Ora, se ti capita di voler utilizzare un browser per visualizzare l'interfaccia RESTful (ovvero durante lo sviluppo/debugging), ti imbatterai in questo limite, ma ci sono strumenti là fuori per aggirare questo problema.

0

5 anni dopo, sembra esistere un'altra opzione valida: utilizzare il corpo del messaggio di GET. Sto includendo questa risposta come alternativa a tutti i suggerimenti di cui sopra, anche se ha i suoi limiti (fare qualche ricerca).

+1

https://xhr.spec.whatwg.org/#the-send()-method - in base alle ultime specifiche, il corpo passato a XHR 'GET' verrà ignorato – Victor

+0

Google lo mostrerà come un errore sul tuo dominio, non farlo –

0

Questo è facile. Usa POST. HTTP non impone un limite alla lunghezza dell'URL per GET ma i server lo fanno. Sii pragmatico e aggiralo con un POST.

È anche possibile utilizzare un corpo GET (che è consentito) ma si tratta di un doppio smacco in quanto non è corretto utilizzo e probabilmente avrà problemi con il server.

Problemi correlati