REST - Kompromisy między negocjacjami treści za pośrednictwem nagłówka Akceptuj a rozszerzeniami

40

Pracuję nad zaprojektowaniem interfejsu API RESTful. Wiemy, że chcemy zwrócić JSON i XML dla dowolnego zasobu. Myślałem, że zrobimy coś takiego:

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

Jednak ktoś rzucił do tego celu rozszerzenia, na przykład:

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

Jakie są kompromisy z tymi podejściami? Czy najlepiej jest polegać na nagłówku akceptującym, gdy rozszerzenie nie jest określone, ale czy rozszerzyć rozszerzenia, jeśli są określone? Czy to podejście ma wadę?

Brandon Linton
źródło
Z jakiego serwera korzystasz? i jak analizuje adresy URL?
Dipan Mehta
1
Nie mam pojęcia o technicznej (serwerowej) stronie rzeczy. Biorąc to pod uwagę, wolę twoje podejście, ponieważ korzysta ze standardu http, co ułatwia zrozumienie (na przykład, gdy ktoś inny powinien wykonać kilka czynności konserwacyjnych kilka lat później). Możesz polegać na rozszerzeniu, gdy nie określono opcji akceptacji lub ma ona nieoczekiwaną wartość, ale zawsze najpierw wybrałbym standardową metodę.
Treb
@Dipan Hakuję to za pomocą interfejsu API sieci Web MVC4 (wciąż w wersji beta). Wykorzystuje abstrakcje routingu ASP.NET, które są całkiem fajne.
Brandon Linton
1
@Treb Tak, jestem znacznie bardziej fanem używania wartości nagłówka accept. Zastanawiam się, czy jest jakaś wada we wspieraniu obu.
Brandon Linton

Odpowiedzi:

38

To „Jednak filozoficznie - pierwsze podejście jest jedynym podejściem”, a to „Właściwe oficjalne podejście RESTful polega na użyciu nagłówka Accept:”. są powszechnie postrzegane jako przypadek, ale są również absolutnie niepoprawne .

Oto krótki fragment Roy'a Fieldinga (który zdefiniował REST) ​​...

„sekcja 6.2.1 nie mówi, że należy zawsze korzystać z negocjacji treści.” cytować

Ta szczególna rozmowa jest w kontekście nagłówka „Accept-Language:”, ale to samo dotyczy nagłówka „Accept:”, jak wyjaśniono później w jego odpowiedzi ...

„Nie mam pojęcia, dlaczego ludzie nie widzą drugiego i trzeciego linku na górnej stronie

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

wskazują na dwie wersje PDF ”.

Ma na myśli to, że nie ma problemu z używaniem różnych punktów końcowych dla różnych reprezentacji tych samych danych źródłowych. (W tym przypadku jeden punkt końcowy .html i dwa różne punkty końcowe .pdf.)

Również w podobnej dyskusji, tym razem dotyczącej zalet używania parametrów zapytania w porównaniu do używania rozszerzeń plików dla różnych typów mediów ...

„Dlatego zawsze wolę rozszerzenia. Żaden wybór nie ma nic wspólnego z REST.” cytować

Ponownie, to nieco różni się od Akceptuj kontra rozszerzenia plików, ale postawa Fieldinga jest nadal jasna.

Odpowiedź - to naprawdę nie ma znaczenia. Kompromisy między nimi nie są bardzo znaczące i oba są akceptowalnymi stylami.

Tom Christie
źródło
3
Świetnie wyważona odpowiedź. Myślę, że czasami dodawałbym, że „URI” jest oczywiste, że określona treść jest przeznaczona. np. rozszerzenie .html lub .pdf w URI. I w tym przypadku naprawdę nie ma potrzeby wspierania negocjacji treści, a posiadanie treści ukrytej w URI ułatwia ludziom udostępnianie URI i używanie go do łączenia z rzeczami w sposób, który mogą natychmiast wykorzystać. W innych przypadkach, takich jak chcesz uniknąć rozszerzeń URI i / lub chcesz udostępnić internetowy interfejs API obsługujący wiele typów treści json / XML w równym stopniu, nagłówek accept może pasować lepiej.
Tim Lovell-Smith,
Zaktualizowana odpowiedź zawiera nowe linki. Myślę, że grupy Yahoo zmieniły swoją strukturę.
Phil Sturgeon
Nie zgadzam się. Język opisu zasobów zwracany przez serwer powinien być nieistotny dla logiki biznesowej wykonywanej przez punkt końcowy usługi. Posiadanie wielu identyfikatorów URI dla tego samego punktu końcowego usługi, aby pomieścić różne języki opisu zasobów, wydaje się być nieporozumieniem, jak należy konstruować identyfikatory URI REST.
Dejay Clayton
10

Prawidłowym oficjalnym podejściem RESTful jest użycie Accept:nagłówka.

Należy jednak uważać, aby nie zepsuć pamięci podręcznej, co jest jednym z wymagań REST. Musisz mieć Vary: Acceptnagłówek i pamięć podręczną, które to rozumieją. W idealnym świecie miałbyś to, ale w prawdziwym życiu twój wygląd może się różnić. Drugie rozwiązanie nie jest tak czyste, ale może być bardziej praktyczne.

Zauważ też, że niektóre bardzo stare przeglądarki ignorowały nagłówki, zamiast tego polegając na rozszerzeniu.

vartec
źródło
1
Faktycznie niedokładne. Zobacz zaakceptowaną odpowiedź.
Phil Sturgeon
9

Technicznie nie ma to większego znaczenia - Twój serwer internetowy będzie mógł poprawnie przetworzyć go tak, jak wygląda. (Zakładam, że to, ale nie wygląda jak showstopper).

Jednak filozoficznie - pierwsze podejście jest jedynym podejściem. W usłudze REST adres URL faktycznie wskazuje tylko identyfikator URI - który jest tylko zasobem. Pomyśl przez chwilę o tym zasobie, który jest taki sam jak obiekt w programowaniu obiektowym. Ty mów do tego zasobu przez zaledwie 4 metod (aka GET / POST / PUT / DELETE -lub jeśli w ogóle, że transport umożliwia), ale ta metoda nie stać opis obiektu. W ten sam sposób aspektami zwracana wartość nie jest identyfikatorem URI. Obiekt jest nadal czymś, a nie czymś. Xml lub czymś.json

Załóżmy, że jeśli nie chcesz używać nagłówka Accept, ale jeśli nadal chcesz filozoficznie naprawdę RESTOWAĆ, nie mam nic przeciwko:

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

w przeciwieństwie do

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

Ale jak powiedziałem, ta różnica jest tylko filozoficzna.

Dipan Mehta
źródło
+1 Dipan, masz rację, z wyjątkiem jednej rzeczy: / api / coś? Return_type = xml nadal nie jest spokojny . Powodem, dla którego nie jest to RESTful, jest to, że adresy URL są nieprzejrzyste. IOW, z punktu widzenia protokołu, nie ma różnicy między / api / coś / xml i / api / coś? Xml. Zobacz w3.org/DesignIssues/Axioms.html .
Mark E. Haase
0

@vartec: Myślę, że się mylisz

Właściwa oficjalna zasada RESTful mówi, że nic nie powinno być ukryte w nagłówkach HTTP, ponieważ jest to URI, który jest ujawniony lub do którego się odwołuje, wszelkie szczegóły dotyczące żądania / odpowiedzi powinny być dostarczone jako część URI

Dlatego zdecydowanie zalecam unikanie używania nagłówka w celu uzyskania szczegółowych informacji na temat żądania i odpowiedzi i trzymaj się tego

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

Nie jestem w stanie szybko znaleźć referencji, ale odeślemy je z powrotem (faktycznie możesz odnieść się do książki wydawniczej O'reilly „RESTful web services” ( http://shop.oreilly.com/product/9780596529260.do ) co potwierdza to samo

Basav
źródło
17
-1 Zupełnie źle. Po pierwsze, adres URL jest wysyłany w nagłówkach HTTP. Ponadto każdy odrębny adres URL powinien reprezentować odrębny zasób. Kodowania XML i JSON tej samej zawartości wyraźnie nie są 2 różnymi zasobami; są to 2 różne reprezentacje tego samego zasobu.
Mark E. Haase
Nagłówki HTTP są uzasadnionym i zalecanym miejscem do przechowywania „metadanych wiadomości”, takich jak: poświadczenia bezpieczeństwa, identyfikator korelacji, identyfikator sesji, kontekst transakcyjny, formaty danych. Tego rodzaju informacje nie powinny zaśmiecać adresów URL ani ładunku wiadomości.
Paulo Merson