2015-05-13 2 views
1

Я пишу код в Erlang, который принимает HTTP-запросы. У меня есть рабочий код, который показан ниже.Erlang gen_tcp: recv http_request abs_path

Проблема у меня в том, что я не уверен в возвращенном результате gen_tcp:recv.

создать сокет и принимать сокеты, используя

{ok, ListenSock}=gen_tcp:listen(Port, [list,{active, false},{packet,http}]) 
{ok, Sock}=gen_tcp:accept(ListenSock), 

Я принимаю запрос GET (или любой другой), используя

{ok, {http_request, Method, Path, Version}} = gen_tcp:recv(Sock, 0), 
handle_get(Sock, Path); 

Затем, чтобы получить параметры URL (параметры CGI, например, ?foo=1&bar=2) Я должен соответствовать Path со структурой {abs_path, RelativePath}.

handle_get(Sock, ReqPath) -> 
    {abs_path, RelPath} = ReqPath, 
    Parameters = string:substr(RelPath, string:str(RelPath, "?") + 1), 

В то время как я читал через документы Эрланга о gen_tcp и более конкретно метод recv я нашел the page describing HttpPacket.

Грамматика на странице ясно показывает, что Path в HttpPacket, и в этом случае HttpRequest типа, может иметь несколько типов HttpUri.

HttpRequest = {http_request, HttpMethod, HttpUri, HttpVersion} 
HttpUri = '*' 
     | {absoluteURI, 
      http | https, 
      Host :: HttpString, 
      Port :: inet:port_number() | undefined, 
      Path :: HttpString} 
     | {scheme, Scheme :: HttpString, HttpString} 
     | {abs_path, HttpString} 
     | HttpString 

Я понимаю, что я должен поддерживать каждый из этих возможных случаев, однако я не уверен. Мне также интересно, как я могу проверить эти случаи. Я пробовал использовать curl и RESTClient в Firefox, и оба они делают gen_tcp:recv return abs_path.

Чтобы было ясно, как определяется, содержит ли запрос {abs_path, HttpString}, {scheme, Scheme :: HttpString, HttpString} или {absoluteURI,...}, и мне нужно поддерживать их все?

Полный список

start(Port)-> 
    {ok, ListenSock}=gen_tcp:listen(Port, [list,{active, false},{packet,http}]), 
    loop(ListenSock). 


loop(ListenSock) -> 
    {ok, Sock}=gen_tcp:accept(ListenSock), 
    spawn(?MODULE, handle_request, [Sock]), 
    loop(ListenSock). 

%% Takes a TCP socket and receives 
%% http://erlang.org/doc/man/erlang.html#decode_packet-3 
handle_request(Sock) -> 
    {ok, {http_request, Method, Path, _Version}} = gen_tcp:recv(Sock, 0), 

    case (Method) of 
     'GET' -> 
      handle_get(Sock, Path); 
     _ -> 
      send_unsupported_error(Sock) 
    end. 

handle_get(Sock, ReqPath) -> 
    {abs_path, RelPath} = ReqPath, 
    Parameters = string:substr(RelPath, string:str(RelPath, "?") + 1), 
    %% Debugging 
    ParsedParms = httpd:parse_query(Parameters), 
    io:fwrite("Full Path: ~p~nParameters: ~p~n", [RelPath, ParsedParms]), 
    %% End Debugging 
    send_accept(Sock). 
+0

Почему вы пишете собственный веб-сервер?Это больше, чем вы думаете. –

+0

Я не пишу свой собственный веб-сервер. Весь мой код должен сделать, это принять запросы на получение с параметрами в URL-адресе. Я не собираюсь заниматься другим. –

+0

Что относительно заголовков HTTP, сопровождающих запрос GET? –

ответ

1

Вы можете использовать простой сети с поддержкой клиента, такие как Netcat (/usr/bin/nc на моей системе), чтобы отправить любой форме запроса вам нравится. Например, следующий подключается к веб-серверу прослушивает localhost порт 8000 и посылает GET запрос, где путь является URL (обратите внимание, что $ обозначает приглашение оболочки):

$ nc localhost 8000 
GET http://stackoverflow.com HTTP/1.1 

$ 

Программа nc читает его стандартный ввод. Не забудьте нажать дважды после строки GET, чтобы правильно указать конец HTTP-заголовков. Это приводит к gen_tcp:recv вызова на сервере возвращающегося:

{absoluteURI,http,"stackoverflow.com",undefined,"/"} 

Аналогично, следующий будет возвращать путь от gen_tcp:recv что это не {abs_path, ...} кортеж, а просто "../foo":

$ nc localhost 8000 
GET ../foo HTTP/1.1 

$ 

Вы можете легко установить как это происходит в текстовых файлах и загружать их в nc с использованием перенаправления stdin.

+0

Ага, это ответы на все, что я хотел знать! Спасибо! –

Смежные вопросы