Я пишу код в 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).
Почему вы пишете собственный веб-сервер?Это больше, чем вы думаете. –
Я не пишу свой собственный веб-сервер. Весь мой код должен сделать, это принять запросы на получение с параметрами в URL-адресе. Я не собираюсь заниматься другим. –
Что относительно заголовков HTTP, сопровождающих запрос GET? –