Лучшие практики для реализации длительных поисков с помощью REST

В рамках службы REST мне нужно реализовать поисковый вызов. Основная идея заключается в том, что пользователь может POST новый поиск и получить результаты:

POST http://localhost/api/search
GET http://localhost/api/search?id=123

Однако мой поиск может занять несколько минут и возвращать частичные результаты до тех пор, пока это не будет сделано. То есть GET-запрос будет возвращать что-то вроде:

status: running
results: a, b, c.

в то время как следующий GET-запрос может вернуться

status: completed
results: a, b, c, d, e.

Это противоречит семантике запроса RESTful GET. Запрос всегда должен возвращать один и тот же результат при вызове несколько раз. Например, когда пользователь использует прокси-сервер кэширования, полные результаты могут никогда не быть доставлены пользователю.

Вопрос: Есть ли способ обеспечить действительно RESTful реализацию для длительных поисков с частичными результатами?

5 ответов

Решение

Во время выполнения поиска вы можете установить соответствующие заголовки ответа (например, Expires или же max-age), чтобы указать, что ответ не должен кэшироваться (HTTP / 1.1 14.9.3, 13.4).

Как только результат поиска будет завершен, вы можете отправить более подходящее Expires / max-age заголовок, чтобы разрешить или расширить кешируемость результата.

Клиенту придется перезапускать ресурс до тех пор, пока его состояние поиска не будет завершено. Клиент может использовать значение заголовка Expires, чтобы определить, когда он должен повторно запросить обновленные результаты.

Наряду с этим, вы также можете использовать пользовательский код состояния 2XX, чтобы указать, что результат еще не завершен. Может быть HTTP/1.1 299 In Progressили что имеет смысл. Спецификация указывает, что коды состояния HTTP являются расширяемыми.


Для записи, ваше заявление:

Это противоречит семантике запроса RESTful GET. Запрос всегда должен возвращать один и тот же результат при вызове несколько раз.

не верно для запросов GET - ресурсы могут измениться. То, что запросы GET являются идемпотентными, означает лишь то, что "... побочные эффекты от N > 0 идентичных запросов такие же, как и для одного запроса". [спецификация]

Несколько дней назад я случайно наткнулся на сообщение в блоге на Reddit, которое касается вашей проблемы. Возможно, вы захотите проверить это: RESTy long-ops Билла Хиггина.

Приятного чтения.

Это не проблема, если первый запрос GET возвращает частичные результаты, а второй запрос GET возвращает полные результаты. Это связано с тем, что первый запрос GET не приводит к изменению результата второго запроса: этот запрос вернул бы полные результаты, даже если первый GET не был выполнен. "Идемпотент" не означает идентичные результаты. Это означает, что первый GET не влияет на второй GET.

Было бы проблемой, если бы первый запрос GET возвратил частичные результаты, а второй GET вернул бы оставшиеся результаты (первый GET вернул A, B, C; второй GET вернул D, E, F). Здесь первый GET изменяет второй результат, поэтому он не RESTful.

Возможно, это не самый элегантный ответ, но обойдется кэширование прокси: просто не отправляйте один и тот же запрос дважды. Добавьте метку времени к запросу (&time=1318355458). Таким образом, каждый запрос уникален (вы также можете добавить миллисекунды ко времени, если вы запрашиваете> 1 Гц).

Что касается следования доктрине "Запрос должен всегда возвращать один и тот же результат при вызове несколько раз", это логически противоречит цели возврата частичных результатов в разное время для одного и того же запроса.

Можете ли вы подождать вместо опроса, если вы просто хотите получить полные результаты?

Почему вы не можете предоставить ресурс как часть вашего POST, который получит результаты PUT? Вы предоставляете REST-интерфейс "обратного вызова", поэтому вместо опроса клиентский процесс ожидает PUT для предоставленного ресурса. Затем вы можете либо получить результаты, либо результаты могут быть включены в PUT.

Другие вопросы по тегам