Sono interessato a esporre un'interfaccia REST diretta a raccolte di documenti JSON (pensa a CouchDB o Persevere ). Il problema in cui mi imbatto è come gestire l' GET
operazione sulla radice della raccolta se la raccolta è grande.
Ad esempio, fingo di esporre la Questions
tabella di StackOverflow in cui ogni riga è esposta come documento (non che esista necessariamente una tabella di questo tipo, solo un esempio concreto di una considerevole raccolta di "documenti"). La collezione sarà disponibile presso /db/questions
con la solita CRUD api GET /db/questions/XXX
, PUT /db/questions/XXX
, POST /db/questions
è in gioco. Il modo standard per ottenere l'intera raccolta è, GET /db/questions
ma se questo ingenua ogni riga come un oggetto JSON, otterrai un download piuttosto considerevole e molto lavoro da parte del server.
La soluzione è, ovviamente, il paging. Dojo ha risolto questo problema nel suo JsonRestStore tramite un'estensione intelligente conforme a RFC2616 dell'utilizzo Range
dell'intestazione con un'unità di intervallo personalizzata items
. Il risultato è un valore 206 Partial Content
che restituisce solo l'intervallo richiesto. Il vantaggio di questo approccio rispetto a un parametro di query è che lascia la stringa di query per ... query (ad es. GET /db/questions/?score>200
O somesuch, e sì che sarebbe codificato %3E
).
Questo approccio copre completamente il comportamento che desidero. Il problema è che RFC 2616 specifica che su una risposta 206 (sottolineatura mia):
La richiesta DEVE aver incluso un campo di intestazione Range ( sezione 14.35 ) che indica l'intervallo desiderato e MAGGIO ha incluso un campo di intestazione If-Range ( sezione 14.27 ) per rendere condizionale la richiesta.
Questo ha senso nel contesto dell'uso standard dell'intestazione, ma è un problema perché vorrei che la risposta 206 fosse l'impostazione predefinita per gestire l'esplorazione di client / persone casuali ingenui.
Ho esaminato dettagliatamente la RFC alla ricerca di una soluzione, ma non sono stato soddisfatto delle mie soluzioni e sono interessato alla soluzione del problema da parte di SO.
Idee che ho avuto:
- Ritorna
200
con unContent-Range
colpo di testa! - Non penso che sia sbagliato, ma preferirei se fosse un indicatore più ovvio che la risposta è solo contenuto parziale. - Restituzione
400 Range Required
: non esiste uno speciale codice di risposta 400 per le intestazioni richieste, pertanto l'errore predefinito deve essere utilizzato e letto manualmente. Questo rende anche più difficile l'esplorazione tramite browser web (o qualche altro client come Resty). - Usa un parametro di query : l'approccio standard, ma spero di consentire le query alla Persevere e questo taglia lo spazio dei nomi delle query.
- Ritorna
206
! - Penso che la maggior parte dei clienti non impazzirebbe, ma preferirei non andare contro un DEVE nella RFC - Estendi le specifiche! Return
266 Partial Content
: si comporta esattamente come 206 ma risponde a una richiesta che NON DEVE contenere l'Range
intestazione. Immagino che 266 sia abbastanza alto da non dover incorrere in problemi di collisione e ha senso per me, ma non sono chiaro se questo sia considerato tabù o no.
Penso che questo sia un problema abbastanza comune e mi piacerebbe vederlo fatto in una maniera di fatto, quindi io o qualcun altro non stiamo reinventando la ruota.
Qual è il modo migliore per esporre una raccolta completa via HTTP quando la raccolta è grande?
Range = "Range" ":" ranges-specifier
dove quest'ultima in tools.ietf.org/html/rfc2616#section-14.35.1 è descritta semplicemente come "specificatore di intervalli di byte" che deve iniziare con "unità di byte" che è definita come stringa "byte ".
Content-Range
intestazione si applica al corpo (può essere utilizzato con la richiesta durante il caricamento di file di grandi dimensioni ecc. O per la risposta durante il download). L' Range
intestazione viene utilizzata per richiedere un determinato intervallo. Si dovrebbe rispondere 206
quando l' Range
intestazione è stata inclusa nella richiesta. In caso contrario, la risposta potrebbe ancora includere Content-Range
un'intestazione, ma dovrebbe essere il codice di risposta 200
. Questa intestazione in realtà sembra ideale per il paging.