вторник, 15 февраля 2011 г.

Управление обработкой запросов в RESTAS

Добавил в RESTAS экспериментальную возможность: переменные restas:*before-dispatch-request-hook* и restas:*after-dispatch-request-hook*. В эти переменные можно складывать (pushnew) функции, которые будут вызываться соответственно до и после обработки запроса. restas:*before-dispatch-request-hook* может быть полезен, например, для безусловного требования авторизации от пользователей - не-авторизованных пользователей можно перенаправлять на страницу входа или запрашивать HTTP-авторизацию с помощью hunchentoot:require-authorization. А restas:*after-dispatch-request-hook* можно использовать, например, для сбора статистики обращения к различным URL, или можно делать косметическую пост-обработку результата, скажем, добавлять заголовки ответа.

Для иллюстрации использования restas:*before-dispatch-request-hook* я написал тривиальный пример модуля для сбора статистики, посмотреть его можно здесь.

restas:*before-dispatch-request-hook* и restas:*after-dispatch-request-hook* не позволяют серьёзным образом влиять на обработку запроса (хотя с их помощью и можно вносить небольшие изменения), кроме того - они применяются для всех запросов, обрабатываемых веб-сервером.

Есть другая, более тонкая возможность влиять на ход обработки запросов. Например, если необходимо ограничить доступ к маршрутам из какого-либо модуля или проводить тонкую настройку обработки маршрутов из конкретного модуля.
(in-package #:mymodule)

(defclass myroute (restas:route) ())

(defmethod restas:module-routes ((module (eql #.*package*)) submodule)
(let ((routes (call-next-method)))
(iter (for route in routes)
(change-class route 'myroute))
routes))
Здесь объявляется свой класс маршрутов myroute и для конкретного модуля специализируется метод restas:module-routes, в котором основная работа делается с помощью call-next-method, а затем у полученных маршрутов изменяется класс с restas:route на myroute. Теперь можно определить собственные специализации для методов обработки маршрутов и определить произвольную логику обработки любым удобным способом. Для класса myroute имеет смысл специализировать следующие методы:
  • routes:route-check-conditions (route bindings) - проверяется соответствует ли запрос требования маршрута
  • restas:process-route (route bindings) - здесь происходит вызов обработчика маршрута и, соответственно, генерация контента

1 комментарий: