суббота, марта 02, 2013

Rest handler в web-сервере Cowboy, нюансы.

Этот пост - краткий итог моих ковыряний в недрах вебсервера cowboy 0.8, куцых примерах и обрывках документации.
Написано чайником, как конспект самому себе.

Обозначенные жирным шрифтом названия функций - вызываются ковбоем, если он находит их в export`ах модуля. (и естественно, должны быть экспортированы)
Обозначенные курсивом - называем как хотим, т.к. их названия отдаём ковбою мы.

  1. Как обозначить, что наш хэндлер - именно rest handler
    Определяем функцию init/3:

    init(_Transport, _Req, _Opts) -> {upgrade, protocol, cowboy_rest}.


  2. Как получить что-то из middleware в State обработчика  (сессию например):
    Определяем метод rest_init/2.

    rest_init( Req, State ) -> { ok, Req, State }.

  3. Как вернуть что-то на GET запрос:
    1. Cowboy будет проверять поддерживается ли http method запроса нашим хэндлером.
      Чтобы обозначить список поддерживаемых методов, определяем allowed_methods/2:

          allowed_methods( Req, State )->
              {[<<"GET">>, <<"PUT">>, <<"DELETE">>], Req, State}.

    2. определяем тип возвращаемых данных:

      content_types_provided(Req, State) ->
          {[{<<"application/json">>, наш_json_ответ}], Req, State}.
    3. определяем обозначенный обработчик наш_json_ответ/2:
          наш_json_ответ(Req, State) ->
              ... ...
              Json = mochijson2:encode({struct, ResponseObject}),
             {Json, Req, State}.

  4. Как принять PUT запрос.

    1. Cowboy возьмет content-type реквеста и проверит, поддерживается ли он нашим обработчиком.
      Для этого определяем следующую функцию:

      content_types_accepted(Req, State) ->
          {[{{<<"application">>, <<"json">>,
              [{<<"charset">>, <<"UTF-8">>}]}, некий_обработчик}], Req, State }.
      (можно использовать '*')

    2. реализуем обозначенный выше некий_обработчик:
         
      некий_обработчик(Req, State) ->
          Достаем json из тела запроса
          {ok, Body, Req1} = cowboy_req:body(Req),
          Декодируем json
          {struct, Object} = mochijson2:decode(Body),
          делаем что нам нужно,
          ....
          Json = формируем json ответа,
          Req3 = cowboy_req:set_resp_body( НашJsonОтвет, Req1 ),
          { true, Req3, State2 }.

  5. Как принять DELETE request.

    необходимо определить функции delete_resource/2, delete_completed/2
        сначала будет вызван первый, после второй.
       
        Из delete_resource/2 возвращаем {true, Req, State} (true = удаляем, если false будет возвращен 500)

        В delete_completed/2 при необходимости обозначаем, что хотим отдать клиенту, например
        Req2 = cowboy_req:set_resp_body( <<"{}">>, Req ),
        Возвращаем {true, Req2, State}.

Комментариев нет: