Erlang gen_tcp:recv http_request abs_path



我正在在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),

当我阅读有关gen_tcp的Erlang文档时,更具体地说是recv方法,我找到了描述HttpPacket的页面。

页面上的语法清楚地表明,HttpPacket中的Path,在这种情况下,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中使用curlRESTClient,它们都使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).

您可以使用一个简单的具有网络功能的客户端,例如NetCat(我的系统上的/usr/bin/nc)来发送您喜欢的任何形式的请求。例如,以下连接到在localhost端口8000上侦听的Web服务器,并在路径为URL的情况下发送GET请求(请注意$表示Shell提示):

$ 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
$

您可以在文本文件中轻松设置这样的测试变化,并使用stdin重定向将其馈送到nc中。

最新更新