REST: compromessi tra negoziazione dei contenuti tramite Accetta intestazione contro estensioni


40

Sto lavorando alla progettazione di un'API RESTful. Sappiamo di voler restituire JSON e XML per una determinata risorsa. Pensavo che avremmo fatto qualcosa del genere:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

Tuttavia, qualcuno ha lanciato usando le estensioni per questo, in questo modo:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Quali sono i compromessi con questi approcci? È meglio fare affidamento sull'intestazione accetta quando non viene specificata un'estensione, ma onorare le estensioni quando specificate? C'è un inconveniente in questo approccio?


Quale server web stai usando? e come analizza gli URL?
Dipan Mehta,

1
Non ho idea del lato tecnico (server) delle cose. Detto questo, preferisco il tuo approccio, perché utilizza lo standard http, il che rende più facile la comprensione (ad esempio quando si suppone che qualcun altro debba fare un po 'di manutenzione su di esso alcuni anni lungo la strada). Potresti fare affidamento sull'estensione quando l' accettazione non è specificata o ha un valore inaspettato, ma prima andrei sempre con la via standard.
Treb

@Dipan Lo sto hackerando con l'API Web MVC4 (ancora in versione beta). Utilizza le astrazioni di routing di ASP.NET, che sono piuttosto belle.
Brandon Linton

1
@Treb Sì, sono molto più un fan dell'utilizzo del valore dell'intestazione accetta. Mi chiedo se ci sia qualche svantaggio nel supportare entrambi.
Brandon Linton

Risposte:


38

Questo, "Comunque, filosoficamente - il primo approccio è l'unico approccio", e questo "L'approccio RESTful ufficiale corretto è usare Accetta: intestazione". sono ampiamente considerati come il caso, ma sono anche assolutamente errati .

Ecco un breve frammento di Roy Fielding (che ha definito REST) ​​...

"la sezione 6.2.1 non dice che la negoziazione dei contenuti dovrebbe essere usata continuamente." citare

Quella particolare conversazione è nel contesto dell'intestazione "Accept-Language:", ma lo stesso vale anche per l'intestazione "Accept:", come chiarito più avanti nella sua risposta ...

"Non ho idea del perché le persone non possano vedere il secondo e il terzo link nella prima pagina

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

che indicano le due edizioni PDF. "

Ciò che intende dire è che non esiste alcun problema nell'uso di endpoint diversi per diverse rappresentazioni degli stessi dati di origine. (In questo caso un endpoint .html e due endpoint .pdf diversi.)

Anche in una discussione simile, questa volta per quanto riguarda le virtù dell'uso dei parametri della query rispetto all'utilizzo delle estensioni di file per diversi tipi di media ...

"Ecco perché preferisco sempre le estensioni. Nessuna scelta ha a che fare con REST." citare

Ancora una volta, questo è leggermente diverso dalle estensioni Accept vs file, ma la posizione di Fielding è ancora chiara.

Risposta: non ha molta importanza. I compromessi tra i due non sono molto significativi ed entrambi sono stili accettabili.


3
Ottima risposta equilibrata. Penso che aggiungerei a volte è "ovvio" dall'URI che un determinato contenuto è destinato. ad es. estensione .html o estensione .pdf nell'URI. E in questo caso non c'è davvero bisogno di supportare la negoziazione dei contenuti e avere contenuti impliciti nell'URI rende più facile per gli umani condividere l'URI e usarlo per collegarsi alle cose in un modo che possono immediatamente consumare. In altri casi, ad esempio se si desidera evitare estensioni nei propri URI e / o si desidera esporre un'API Web che supporti allo stesso modo più tipi di contenuto json / XML, un'intestazione accetta può adattarsi meglio.
Tim Lovell-Smith,

Risposta aggiornata per contenere nuovi collegamenti. Penso che i gruppi yahoo abbiano cambiato la loro struttura.
Phil Sturgeon,

Non sono d'accordo. Il linguaggio di descrizione delle risorse restituito dal server dovrebbe essere irrilevante per la logica aziendale eseguita dall'endpoint del servizio. Avere più URI per lo stesso endpoint di servizio, solo per adattarsi a linguaggi di descrizione delle risorse diversi, sembra un malinteso su come dovrebbero essere costruiti gli URI REST.
Dejay Clayton,

10

L'approccio RESTful ufficiale corretto è utilizzare l' Accept:intestazione.

Tuttavia, è necessario fare attenzione a non violare la cache, che è uno dei requisiti di REST. Devi avere Vary: Acceptintestazione e cache che lo capisca. Nel mondo ideale lo avresti, ma nella vita reale il tuo millage può variare. Quindi la seconda soluzione non è così pulita, ma potrebbe essere più pratica.

Inoltre, tieni presente che alcuni browser molto vecchi usavano ignorare le intestazioni, basandosi invece sull'estensione.


1
In realtà impreciso. Vedi risposta accettata
Phil Sturgeon,

9

Tecnicamente non ha molta importanza: il tuo server web sarà in grado di passare il processo in modo appropriato come sembra. (Sto assumendo questo, ma non sembra uno showtopper).

Tuttavia, filosoficamente, il primo approccio è l'unico approccio. In REST, l'URL in realtà punta solo a un URI, che è solo una risorsa. Pensa per un momento a questa risorsa come all'oggetto nella programmazione orientata agli oggetti. Si parla di questa risorsa attraverso solo 4 metodi (aka GET / POST / PUT / DELETE -o semmai che il trasporto permette), ma tale metodo non diventi descrizione dell'oggetto. Allo stesso modo, gli aspetti il ​​valore restituito non è l'URI. L'oggetto è ancora qualcosa e non qualcosa.xml o qualcosa.json

Supponiamo che se non si desidera utilizzare l'intestazione Accept, ma se si desidera comunque essere veramente REST filosoficamente, non mi dispiacerà qualcosa del tipo:

GET /api/something?parm1=value1&return_type=xml

al contrario di

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Ma come ho detto, questa differenza è solo filosofica.


+1 Dipan, hai ragione tranne una cosa: / api / qualcosa? Return_type = xml non è ancora riposante . Il motivo per cui non è RESTful è che gli URL sono opachi. IOW, dal punto di vista del protocollo, non vi è alcuna differenza tra / api / qualcosa / xml e / api / qualcosa? Xml. Vedi w3.org/DesignIssues/Axioms.html .
Mark E. Haase,

0

@vartec: penso che ti sbagli

Il corretto principio RESTful ufficiale dice che nulla dovrebbe essere nascosto nelle intestazioni HTTP in quanto è l'URI che è esposto o referenziato, ogni dettaglio sulla richiesta / risposta dovrebbe essere fornito come parte dell'URI

Quindi consiglio vivamente di evitare di usare l'intestazione per i dettagli su richiesta e risposta, e di attenermi

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Non sono in grado di trovare rapidamente i riferimenti, ma posterò di nuovo con loro (in realtà potresti fare riferimento al libro di pubblicazione O'reilly "RESTful web services" ( http://shop.oreilly.com/product/9780596529260.do ) che conferma lo stesso


17
-1 Completamente sbagliato. Per prima cosa, l'URL viene inviato nelle intestazioni HTTP. Inoltre, ogni URL distinto dovrebbe rappresentare una risorsa distinta. Le codifiche XML e JSON dello stesso contenuto non sono chiaramente 2 risorse diverse; sono 2 diverse rappresentazioni della stessa risorsa.
Mark E. Haase,

Le intestazioni HTTP sono un luogo legittimo e consigliato per l'archiviazione di "metadati di messaggistica", quali: credenziali di sicurezza, identificatore di correlazione, ID di sessione, contesto transazionale, formati di dati. Questo tipo di informazioni non dovrebbe ingombrare gli URL o il payload del messaggio.
Paulo Merson,
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.