我正在用 Erlang 编写接受 HTTP 请求的代码。我有如下所示的工作代码。
我遇到的问题是我不确定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),
当我阅读 Erlang 的文档时gen_tcp
,更具体地说,recv
我找到了描述HttpPacket
.
页面上的语法清楚地表明Path
in 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
我知道我必须支持每一种可能的情况,但我不确定。我也想知道如何测试这些案例。我曾尝试在 Firefox 中使用curl
andRESTClient
并且它们都gen_tcp:recv
返回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).