gen tcp - Erlang gen_tcp:recv http_request abs_path -
i'm writing code in erlang accepts http requests. have working code shown below.
the problem have i'm unsure returned result of gen_tcp:recv.
i create listening socket , accept sockets using
{ok, listensock}=gen_tcp:listen(port, [list,{active, false},{packet,http}]) {ok, sock}=gen_tcp:accept(listensock), i accept request (or other) using
{ok, {http_request, method, path, version}} = gen_tcp:recv(sock, 0), handle_get(sock, path); then, url parameters (cgi parameters, e.g., ?foo=1&bar=2) have match path structure {abs_path, relativepath}.
handle_get(sock, reqpath) -> {abs_path, relpath} = reqpath, parameters = string:substr(relpath, string:str(relpath, "?") + 1), while reading through docs of erlang gen_tcp , more recv method found the page describing httppacket.
the grammar on page shows path in httppacket, , in case httprequest type, can have multiple types of 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 i understand have support each of these possible cases, not sure. wondering how can test these cases. have tried using curl , restclient in firefox , both of them make gen_tcp:recv return abs_path.
so clear, how determined whether request holds {abs_path, httpstring}, {scheme, scheme :: httpstring, httpstring} or {absoluteuri,...} , need support of them?
full listing
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 tcp socket , 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).
you can use simple network-capable client such netcat (/usr/bin/nc on system) send whatever form of request like. example, following connects web server listening on localhost port 8000 , sends get request path url (note $ denotes shell prompt):
$ nc localhost 8000 http://stackoverflow.com http/1.1 $ the nc program reads standard input. sure hit enter twice after get line indicate end of http headers. results in gen_tcp:recv call on server returning:
{absoluteuri,http,"stackoverflow.com",undefined,"/"} similarly, following return path gen_tcp:recv that's not {abs_path, ...} tuple, rather "../foo":
$ nc localhost 8000 ../foo http/1.1 $ you can set test variations these in text files , feed them nc using stdin redirection.
Comments
Post a Comment