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' GEToperazione sulla radice della raccolta se la raccolta è grande.
Ad esempio, fingo di esporre la Questionstabella 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/questionscon 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/questionsma 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 Rangedell'intestazione con un'unità di intervallo personalizzata items. Il risultato è un valore 206 Partial Contentche 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>200O 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
200con unContent-Rangecolpo 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'Rangeintestazione. 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-specifierdove 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-Rangeintestazione 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' Rangeintestazione viene utilizzata per richiedere un determinato intervallo. Si dovrebbe rispondere 206quando l' Rangeintestazione è stata inclusa nella richiesta. In caso contrario, la risposta potrebbe ancora includere Content-Rangeun'intestazione, ma dovrebbe essere il codice di risposta 200. Questa intestazione in realtà sembra ideale per il paging.