Erlangã§TCPãµã¼ããæ¸ãã¦ã¿ã¾ãã
ãã¼ã«ã«ãããã·ãä½ã£ã¦ã¿ããã§ãã
-module(serv).
-compile(export_all).
-compile([start/1]).
-define(TCP_OPTIONS, [binary, {packet, raw}, {active, false}, {reuseaddr, true}]).
start (Port) ->
spawn(?MODULE, init, [Port, self()]).
init(Port, Pid) ->
{ok, Listen} = gen_tcp:listen(Port, ?TCP_OPTIONS),
accept_loop(Listen, Pid).
accept_loop(Listen, Pid) ->
case gen_tcp:accept(Listen) of
{ok, Accept} ->
spawn(?MODULE, accept_handler, [Accept, Pid]),
accept_loop(Listen, Pid)
end.
accept_handler(Accept, Pid) ->
inet:setopts(Accept, [{packet, http}]),
{ok, {http_request, Method, URL, {Major, Minor}}} = gen_tcp:recv(Accept, 0),
Headers = recv_request_headers(Accept),
inet:setopts(Accept, [{packet, raw}]),
Body =
case lists:keyfind('Content-Length', 1, Headers) of
{'Content-Length', Len} when is_integer(Len) ->
gen_tcp:recv(Accept, Len);
_ -> <<>>
end,
io:format("~p, ~p, ~p/~p~n~p~n~p~n",
[Method, URL, Major, Minor, Headers, Body]),
case URL of
{abs_path, Path} ->
Txt = "<html><body><a>not found</a></body></html>",
gen_tcp:send(Accept, "HTTP/1.1 404 not-found\r\nContent-Length: "),
gen_tcp:send(Accept, integer_to_list(length(Txt))),
gen_tcp:send(Accept, "\r\n\r\n"),
gen_tcp:send(Accept, Txt);
{absoluteUrl, Protocol, Host, Port, Path} ->
Txt = "<html><body><a>not found</a></body></html>",
gen_tcp:send(Accept, "HTTP/1.1 404 not-found\r\nContent-Length: "),
gen_tcp:send(Accept, integer_to_list(length(Txt))),
gen_tcp:send(Accept, "\r\n\r\n"),
gen_tcp:send(Accept, Txt)
end,
case lists:keyfind('Connection', 1, Headers) of
{'Connection', "keep-alive"} ->
accept_handler(Accept, Pid);
_ ->
gen_tcp:close(Accept)
end.
recv_request_headers(Accept) ->
recv_request_headers(Accept, []).
recv_request_headers(Accept, Hs) ->
case gen_tcp:recv(Accept, 0) of
{ok, http_eoh} -> % end of header
Hs;
{ok, {http_header, _, Key, _, Val}} ->
recv_request_headers(Accept, [{Key,Val} | Hs])
end.
0 件のコメント:
コメントを投稿