Я разрабатываю веб-сервис RESTful с использованием WebApi, и мне было интересно, какие HTTP-ответы и тела ответов нужно возвращать при обновлении / создании объектов.
Например, я могу использовать метод POST для отправки некоторого JSON в веб-сервис, а затем создать объект. Рекомендуется ли затем установить для HTTP-статуса статус созданный (201) или ok (200) и просто вернуть сообщение, например «Новый сотрудник добавлен», или вернуть объект, который был отправлен изначально?
То же самое касается метода PUT. Какой HTTP-статус лучше всего использовать и нужно ли возвращать созданный объект или просто сообщение? Учитывая тот факт, что пользователь в любом случае знает, какой объект он пытается создать / обновить.
Есть предположения?
Пример:
Добавить нового сотрудника:
POST /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Name" : "Joe Bloggs",
"Department" : "Finance"
}
}
Обновить существующего сотрудника:
PUT /api/employee HTTP/1.1
Host: localhost:8000
Content-Type: application/json
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Ответы:
Ответ с созданным / обновленным объектом
HTTP/1.1 201 Created
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Employee": {
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
}
Ответ только с сообщением:
HTTP/1.1 200 OK
Content-Length: 39
Content-Type: application/json; charset=utf-8
Date: Mon, 28 Mar 2016 14:32:39 GMT
{
"Message": "Employee updated"
}
Ответ только с кодом состояния:
HTTP/1.1 204 No Content
Content-Length: 39
Date: Mon, 28 Mar 2016 14:32:39 GMT
UPDATE/INSERT ... RETURNING
вариант Postgresql для SQL. Это очень удобно, особенно потому, что сохраняет представление новых данных и запрос на обновленную версию на атомарном уровне.Ответы:
Как и в большинстве вещей, это зависит. Ваш компромисс - простота использования и размер сети. Для клиентов может быть очень полезно увидеть созданный ресурс. Он может включать в себя поля, заполненные сервером, такие как время последнего создания. Поскольку вы, кажется, включаете
id
вместо использованияhateoas
, клиенты, вероятно, захотят увидеть идентификатор для ресурса, который они только чтоPOST
редактировали.Если вы не включили созданный ресурс, не создавайте произвольное сообщение. Поля 2xx и Location являются достаточной информацией, чтобы клиенты могли быть уверены, что их запрос был правильно обработан.
источник
Лично я всегда только возвращаюсь
200 OK
.Процитировать ваш вопрос
Зачем добавлять дополнительную пропускную способность (за которую, возможно, придется платить), чтобы сообщить клиенту, что он уже знает?
источник
200
/204 No Content
чтобы избежать путаницы jQuery и тому подобное.@iswinky Я бы всегда отправлял полезные данные в случае как POST, так и PUT.
В случае POST вы можете создать объект с внутренним идентификатором или UUID. Следовательно, имеет смысл отправить обратно полезную нагрузку.
Точно так же в случае PUT вы можете игнорировать некоторые поля пользователя (скажем, неизменяемые значения), или в случае PATCH данные могут быть изменены и другими пользователями.
Отправка данных в том виде, в котором они были сохранены, всегда является хорошей идеей и определенно не вредит. Если вызывающему абоненту не нужны эти возвращенные данные, он не будет их обрабатывать, а просто использует statusCode. В противном случае они могут использовать эти данные для обновления пользовательского интерфейса.
Только в случае УДАЛЕНИЯ я бы не отправил обратно полезную нагрузку и сделал бы либо 200 с содержимым ответа, либо 204 без содержимого ответа.
Изменить: Благодаря некоторым комментариям ниже, я переписываю свой ответ. Я до сих пор придерживаюсь того, как я проектирую свои API и отправляю ответные ответы, но я думаю, что имеет смысл уточнить некоторые мои мысли о дизайне.
а) Когда я говорю «отправить обратно полезную нагрузку», я на самом деле хотел сказать «отправить обратно данные ресурса», а не ту же полезную нагрузку, которая пришла в запросе. Пример: если вы отправите полезную нагрузку create, я могу в бэкэнде создать другие объекты, такие как UUID и (возможно) временные метки и даже некоторые (графические) соединения. Я бы отправил все это обратно в ответ (а не только полезную нагрузку запроса как есть - что бессмысленно).
б) я бы не стал отправлять ответы обратно, если полезная нагрузка очень велика. Я обсуждал это в комментариях, но я хотел бы предостеречь о том, что я постараюсь сделать все возможное, чтобы спроектировать свои API или ресурсы так, чтобы они не имели очень большой полезной нагрузки. Я бы попытался разбить ресурсы на более мелкие и управляемые объекты, чтобы каждый ресурс определялся 15-20 атрибутами JSON, а не больше.
В случае, если объект очень большой или родительский объект обновляется, я бы отправил обратно вложенные структуры как hrefs.
Суть в том, что я бы определенно попытался отправить обратно данные, которые имеют смысл для потребителя / пользовательского интерфейса, чтобы немедленно обработать и выполнить с помощью атомарного действия API, вместо того, чтобы идти и получать еще 2-5 API, чтобы обновить пользовательский интерфейс после публикации. создание / обновление данных.
Интерфейсы между серверами API могут думать по-другому об этом. Я сосредотачиваюсь на API, которые управляют пользовательским опытом.
источник
Ссылаясь на ссылку RFC стандартов , вы должны вернуть 201 (созданный) статус при успешном сохранении ресурса запроса с помощью Post. В большинстве приложений идентификатор ресурса генерируется самим сервером, поэтому рекомендуется возвращать идентификатор созданного ресурса. Возврат всего объекта - это накладные расходы для запроса Post. Идеальной практикой является возвращение URL-адреса вновь созданного ресурса.
Например, вы можете обратиться к следующему примеру, который сохраняет объект Employee в базу данных и возвращает URL-адрес вновь созданного объекта ресурса в качестве ответа.
Эта конечная точка отдыха возвратит ответ в виде:
Статус 201 - СОЗДАН
Расположение заголовка → http: // localhost: 8080 / employee / 1
источник
Я бы сделал полезную нагрузку в возвращаемом теле условной к параметру HTTP.
Чаще всего лучше возвращать некоторый контент обратно потребителю API, чтобы избежать ненужных циклов (одна из причин существования GraphQL).
На самом деле, поскольку наши приложения становятся более интенсивными и распределенными, я стараюсь соблюдать это правило:
Мое руководство :
Каждый раз, когда есть сценарий использования, который требует GET сразу после POST или PUT, в этом случае лучше всего просто вернуть что-то в ответе POST / PUT.
Как это делается и какой тип контента возвращать обратно из PUT или POST, зависит от конкретного приложения. Теперь было бы интересно, если бы приложение могло параметризовать тип «содержимого» в теле ответа (хотим ли мы просто местоположение нового объекта, или некоторых полей, или всего объекта и т. Д.)
Приложение может определить набор параметров, которые POST / PUT может получить для управления типом «содержимого», возвращаемого в теле ответа. Или он может закодировать какой-то запрос GraphQL в качестве параметра (я вижу, что это полезно, но также может стать кошмаром обслуживания).
В любом случае, мне кажется, что:
Итак, 1) сделай это, но 2) сделай это простым.
Другой вариант, который я видел, это люди, создающие альтернативные конечные точки (скажем, / customer для POST / PUT, которые ничего не возвращают в теле и / customer_with_details для POST / PUT для / клиентов, но которые возвращают что-то в теле ответа.)
Я бы избегал такого подхода. Что происходит, когда вам по закону необходимо вернуть другой тип контента? Одна конечная точка для каждого типа контента? Не масштабируется и не поддерживается.
источник