Чи слід повертати відповідь 204 або 404, коли ресурс не знайдено?


15

Я розробляю простий RESTful сервіс для турнірів та розкладів. Коли турнір створюється за допомогою POST-запиту, що містить тіло JSON, турнір вставляється у a BiMap, оголошений таким чином у реалізації DAO:

private BiMap<String, Tournament> tournaments = Maps.synchronizedBiMap(HashBiMap.create());

Коли створюється турнір, його асоційований рядовий ідентифікатор повертається, щоб користувач міг мати майбутнє посилання на цей турнір. Він / вона може отримати інформацію з нового турніру, виконавши такий запит:

GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39

Але що робити, якщо не знайдеться турнір з таким ідентифікатором? Поки що я повертаю відповідь 204. Ну, Джерсі робить це для мене, коли повертається nullз одного зі своїх методів. Це метод, який відповідає маршруту вище:

@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("id") String id) {
    Optional<Tournament> optTournament = tournamentDao.getTournament(id);
    if (optTournament.isPresent())
        return optTournament.get();
    return null;
}

Моє запитання: чи нормально повернути 204: No Contentвідповідь, чи 404натомість це відповідь, оскільки ресурс не знайдено?

Якщо я повинен змінити його на 404, очевидне питання: я повинен змінити правильний підпис методу? Оскільки зараз турнір (типу Tournament) не може бути повернутий, метод повинен виглядати інакше. Чи слід використовувати цей Responseтип як тип повернення?

Відповіді:


32

HTTP 204означає, що щось було знайдено, але воно порожнє. Наприклад, уявіть, що ви подаєте файли журналів через HTTP із запитами, такими як http://example.com/logs/ evidencedate-goes-тут] . 18 травня 2015 року:

  • http://example.com/logs/2015-05-19 повернеться HTTP 404, а це означає, що журналів немає, тому що, ну, важко записати майбутнє.

  • http://example.com/logs/2015-05-18 , однак, повернеться або HTTP 200з записами журналу у вмісті відповіді, або HTTP 204якщо файл журналу створено, але журнали для цього ще не записані дата.

Якщо ви надаєте nullрамках як відповідь на запит, він передбачає, що ви знайшли запис, і цей запис, таким чином, порожній HTTP 204. Натомість вам слід throw new NotFoundException();вказати рамці, що запис не існує, щоб він генерував a HTTP 404.

Якщо я повинен змінити його на 404, очевидне питання: я повинен змінити правильний підпис методу?

Ні, ви цього не робите. Це приємна річ throw new NotFoundException();. Він буде працювати незалежно від реального типу повернення вашого методу.


5
Візьміть особливу увагу на RFC 2616 . 204 відповіді відповідають специфікаціям лише якщо ви повністю опускаєте тіло повідомлення. В якійсь мірі суть відповіді 204 полягає в тому, щоб сказати: "ні, не випадково я повернув не зміст". Для розширення прикладу MainMa: Якщо інструмент пошуку журналу виплюнув текстові файли (наприклад, тонка обгортка навколо файлів журналу, яка просто виплює файл журналу як є), для порожнього файлу журналу буде доречним 204. Якщо відповідь був порожнім об'єктом JSON (наприклад, {content: ''}), відповідь 204 була б недоречною.
Брайан

" тому що, ну, важко записати майбутнє ". - Цей біт залежить від довільної дати; чому б не зробити це чимось, що не вимагає, щоб читач робив вигляд, що це не сьогодні? Можливо, використання 2015-02-29було б краще, оскільки це дата, яка взагалі не існує?
Фонд позову Моніки

3

Ви повинні повернути 404. Ви можете це зробити, кинувши NotFoundException ( https://jersey.java.net/apidocs/2.6/jersey/javax/ws/rs/NotFoundException.html ).

Також зверніть увагу на це питання ТАК, чи потрібно контролювати тип повернення вмісту /programming/23858488/how-i-return-http-404-json-xml-response-in-jax-rs- трикотаж на онкате


1

Ваш запит є GET http://localhost:8080/eventscheduler/c15268ce-474a-49bd-a623-b0b865386f39.

Якщо http://localhost:8080/eventscheduler/не існує кінцевої точки, слід повернути 404. Ви намагаєтеся отримати доступ до ресурсу ( /eventscheduler/), який не існує. Це вказувало б клієнту, на якому існує сервер localhost:8080, але в eventschedulerкінцевій точці нічого немає .

Якщо http://localhost:8080/eventscheduler/існує як кінцева точка, але потрібні ресурси недоступні, помилка 5xx підходить. Хорошим прикладом цього може бути, якщо база даних буде в автономному режимі, де ви можете повернути 503. Звичайно, ви можете просто повернути загальну помилку 500 замість конкретного екземпляра.

Якщо http://localhost:8080/eventscheduler/існує, але річ, представлена ​​ним c15268ce-474a-49bd-a623-b0b865386f39, не існує, я б повернув 200 із тілом із зазначенням деталей. Кінцева точка існує, зроблений запит був повністю дійсним і міг бути оброблений, але збігу не було.

Якщо запит вашого клієнта до кінцевої точки був неправдивим, ви подивитесь на інші помилки 4xx. Ви можете вказати, що клієнт не має права доступу до кінцевої точки або предметів, які запитуються за допомогою 401 або 403, або може використовувати 400, щоб вказати, що запит недійсний. З будь-яким із них додаткова інформація може бути надана органу реагування.


Не потрібно розрізняти кінцеву точку та ресурс. Якщо URI не відповідає жодним ресурсам, з будь-якої причини сервер повинен повернути 404.
bdsl

Перевірте код відповіді на цьому веб-сайті, чи є приклад того, як сайт робить правильно. Це веб-сайт, а не API, але застосовується та сама специфікація http. softwareengineering.stackexchange.com/questions/266183385
bdsl

@bdsl Я можу вам сказати, що це абсолютно неправильно. Наприклад, я взаємодію зі службою користувача, яка може повернути профіль користувача. Скажімо, що ця кінцева точка є /userі використовується як би /user?email=test@example.com. Як споживач API, я хочу знати, якщо /userз якихось причин не існує сервера (можливо, він був доданий у v2 API і сервер перебуває на v1 або він був перейменований у v3) або якщо користувач із електронною поштою test@example.comне існує. Перший - це 404, другий - номер 200 із тілом, який не вказує користувача з цією електронною адресою.
Томас Оуенс

@bdsl Це добре, але це не означає, що це правильно чи найкраще. Я також не думаю, що ви можете порівнювати веб-сайт, розроблений для взаємодії з людиною через веб-браузер, та API, призначений для використання в програмній системі.
Томас Оуенс

1
Це питання обговорюється далі у youtube.com/watch?v=nSKp2StlS6s
bdsl
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.