[Cowboy] HTTP/1.1 400 Bad Request

210 views
Skip to first unread message

Alexander Kovalev

unread,
Jul 22, 2013, 2:37:35 AM7/22/13
to erlang-...@googlegroups.com
Привет. 
Есть хендлер, предназначенный для обработки ajax запросов со страницы
Запускаю последовательно несколько одинаковых запросов (около 20 достаточно для гарантированного воспроизведения проблемы)
При get запросах все ок, при post - периодически получаю такой ответ:
HTTP/1.1 400 Bad Request
connection: close
server: Cowboy
date: Mon, 22 Jul 2013 06:09:17 GMT
content-length: 0

При этом в консоли никаких сообщений от ковбоя не появляется и управление обработчику не передается вообще
Попытки определить источник проблемы не привели ни к чему толковому. Гугл по этой проблеме возвращает только двухгодичной давности такую же проблему с пустым телом запроса, у меня запрос не пустой
В какую сторону можно копнуть?

Ковбой - {git, "https://github.com/extend/cowboy.git", {branch, "master"}},
    {ok, _} = cowboy:start_http(
                        http
, 100,
                       
[{port, HttpPort}],
                       
[{env, [{dispatch, DispatchRules}]}]),

Хендлер
-module(sg_rest_handler).
-define(CT_JSON, {<<"content-type">>, <<"application/json">>}).
-define(bta(Data), binary_to_atom(Data, utf8)).
-export([init/3, handle/2, terminate/3]).
-export([test/3]).

init
({tcp, http}, Req, _Opts)    -> {ok, Req, undefined_state}.
terminate
(_Reason, _Req, _State) -> ok.
handle
(Req, State)               -> {ok, dispatch(Req), State}.

test
('POST', [_Data] , _Req) -> ok;
test
('GET',  [_Data] , _Req) -> ok.

dispatch
(Req) ->
   
{Method, _}    = cowboy_req:method(Req),
   
{[Fn|Data], _} = cowboy_req:path_info(Req),
   
Result = apply(?MODULE, ?bta(Fn), [?bta(Method), Data, Req]),
    json
(Result, Req).
   
json
(Data, Req) ->
   
{ok, Reply} = cowboy_req:reply(200, [?CT_JSON], json_encode(Data), Req),
   
Reply.

json_encode
(Data)  -> lists:flatten(mochijson2:encode(Data)).

Petr Kozorezov

unread,
Jul 22, 2013, 11:24:57 AM7/22/13
to erlang-...@googlegroups.com
О©╫О©╫О©╫ 2 О©╫О©╫О©╫-О©╫О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫, О©╫ чёО©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫:)
О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫ "{[Fn|Data], _} = cowboy_req:path_info(Req)".
О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫!
О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫, О©╫.О©╫. О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫ path_info О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫.

On 22.07.13, 10:37, Alexander Kovalev wrote:
О©╫О©╫О©╫О©╫О©╫О©╫.О©╫
О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ ajax О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ (О©╫О©╫О©╫О©╫О©╫ 20 О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫)
О©╫О©╫О©╫ get О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫, О©╫О©╫О©╫ post - О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫:
HTTP/1.1 400 Bad Request
connection: close
server: Cowboy
date: Mon, 22 Jul 2013 06:09:17 GMT
content-length: 0

О©╫О©╫О©╫ О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫
О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫. О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫ О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫
О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫?

О©╫О©╫О©╫О©╫О©╫О©╫ - {git, "https://github.com/extend/cowboy.git", {branch, "master"}},
О©╫ О©╫ {ok, _} = cowboy:start_http(
О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ http
, 100,
О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫
[{port, HttpPort}],
О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫
[{env, [{dispatch, DispatchRules}]}]),

О©╫О©╫О©╫О©╫О©╫О©╫О©╫
-module(sg_rest_handler).
-define(CT_JSON, {<<"content-type">>, <<"application/json">>}).
-define(bta(Data), binary_to_atom(Data, utf8)).
-export([init/3, handle/2, terminate/3]).
-export([test/3]).


init
({tcp, http}, Req, _Opts) О©╫ О©╫-> {ok, Req, undefined_state}.

terminate
(_Reason, _Req, _State) -> ok.

handle
(Req, State) О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ О©╫ -> {ok, dispatch(Req), State}.


test
('POST', [_Data] , _Req) -> ok;

test
('GET', О©╫[_Data] , _Req) -> ok.

dispatch
(Req) ->
О©╫ О©╫
{Method, _} О©╫ О©╫= cowboy_req:method(Req),
О©╫ О©╫
{[Fn|Data], _} = cowboy_req:path_info(Req),
О©╫ О©╫
Result = apply(?MODULE, ?bta(Fn), [?bta(Method), Data, Req]),
О©╫ О©╫ json
(Result, Req).
О©╫ О©╫
json
(Data, Req) ->
О©╫ О©╫
{ok, Reply} = cowboy_req:reply(200, [?CT_JSON], json_encode(Data), Req),
О©╫ О©╫
Reply.

json_encode
(Data) О©╫-> lists:flatten(mochijson2:encode(Data)).
--
--
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫: http://groups.google.com/group/erlang-russian
О©╫О©╫О©╫О©╫О©╫О©╫О©╫: http://erlanger.ru
О©╫О©╫О©╫: xmpp://erl...@conference.jabber.ru
О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫: xmpp://erlang...@conference.jabber.ru
О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫: http://erlanger.ru/ru/erlang-at-conference-jabber-ru
О©╫
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫: erlang-...@googlegroups.com
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫: erlang-russia...@googlegroups.com
---
О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ Erlang О©╫О©╫-О©╫О©╫О©╫О©╫О©╫О©╫.
О©╫
О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫, О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫ О©╫О©╫О©╫О©╫О©╫ erlang-russia...@googlegroups.com.
О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫: https://groups.google.com/groups/opt_out.
О©╫
О©╫

Alexander Kovalev

unread,
Jul 23, 2013, 3:00:34 AM7/23/13
to erlang-...@googlegroups.com
К сожалению, я не могу прочитать ваш ответ
О©╫О©╫О©╫: xmpp://erlang@conference.jabber.ru
О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫: xmpp://erlang-talks@conference.jabber.ru

Alexander Kovalev

unread,
Jul 23, 2013, 3:03:45 AM7/23/13
to erlang-...@googlegroups.com
Но мне кажется, вы правы, судя по месту, которое процитировано. Я только что осознал, что игнорировать возвращенный req от ковбойских методов — хреново


On Monday, July 22, 2013 7:24:57 PM UTC+4, petr.kozorezov wrote:
О©╫О©╫О©╫: xmpp://erlang@conference.jabber.ru
О©╫О©╫О©╫ О©╫О©╫О©╫ О©╫О©╫О©╫О©╫О©╫О©╫О©╫: xmpp://erlang-talks@conference.jabber.ru

Petr Kozorezov

unread,
Jul 23, 2013, 3:31:42 AM7/23/13
to erlang-...@googlegroups.com
Дня 2 как-то убил пытаясь понять, в чём проблема:)
А она оказалась в стоке вроде этой "{[Fn|Data], _} = cowboy_req:path_info(Req)".
Нельзя не в коем случае игнорировать новый реквест, который отдаёт ковбой!
Именно его нужно использовать дальше, т.к. ковбой может в path_info делать чтение данных и модифицировать буферы, которые лежат в структуре запроса.
--
--
Страница рассылки: http://groups.google.com/group/erlang-russian
Новости: http://erlanger.ru
Чат: xmpp://erl...@conference.jabber.ru
Чат для оффтопа: xmpp://erlang...@conference.jabber.ru
Правила, действующие в чате и рассылке: http://erlanger.ru/ru/erlang-at-conference-jabber-ru
 
Написать письмо: erlang-...@googlegroups.com
Отписаться: erlang-russia...@googlegroups.com
---
Вы получили это сообщение, поскольку подписаны на группу Erlang по-русски.
 
Чтобы отказаться от подписки на эту группу и перестать получать из нее сообщения, отправьте электронное письмо на адрес erlang-russia...@googlegroups.com.
Настройки подписки и доставки писем: https://groups.google.com/groups/opt_out.
 
 

Alexander Dergachev

unread,
Jul 23, 2013, 4:23:23 AM7/23/13
to erlang-...@googlegroups.com
там написано о том, что нельзя игнорировать новые реквесты, которые возвращают функции ковбоя, например:

    {[Fn|Data], _} = cowboy_req:path_info(Req),

path_info/1 возвращает обновленный (возможно) Req, а ты его игнорируешь, и дальше используешь первоначальный, это неправильно, если cowboy_req фунция возвращает {что-то, Req}, то дальше необходимо использовать уже этот Req.

With Best Regards,
Alexander Dergachev


2013/7/23 Alexander Kovalev <ass.k...@gmail.com>

Sergey Prokhorov

unread,
Jul 23, 2013, 5:17:59 AM7/23/13
to erlang-...@googlegroups.com
Ну и в догонку:
1)
json_encode(Data)  -> lists:flatten(mochijson2:encode(Data)).
lists:flatten/1 тоже по возможности избегайте. Либо используйте как есть (вложенный список) либо, если очень хочется, используйте iolist_to_binary/1. Вложенный список / iolist в данном случае даже предпочтительнее.

2) binary_to_atom/1 по возможности тоже избегайте. После того как атакующий (или ваш же тестировщик) несколько миллионов раз сделает (псевдокод)
for i in 1..1200000:
   
get("http://your-service.com/rest/$i")
Таким образом, что ваш хендлер будет делать binary_to_atom($i), у вас просто упадёт Erlang VM т.к. количество атомов ограниченное http://www.erlang.org/doc/efficiency_guide/advanced.html#id69276

понедельник, 22 июля 2013 г., 10:37:35 UTC+4 пользователь Alexander Kovalev написал:

Alexander Kovalev

unread,
Jul 23, 2013, 6:02:20 AM7/23/13
to erlang-...@googlegroups.com
1. json использую временно, для прототипа — после отладки перевожу на websockets/bert
2. в курсе, это пока тоже для быстрого прототипирования. думал потом захардкодить все что нужно. 
какие вообще есть best practices для диспатчинга? мне в голову только словарь <путь>:<обработчик> приходит (например, в виде генсервера с апи получения и связывания обработчиков)
Reply all
Reply to author
Forward
0 new messages