Search code examples
socketserlangwebserver

Web page only displaying after server stopped


I am writing a home-made web server in Erlang for learning purposes. The current implementation can parse a HTTP GET request and respond accordingly. The problem is that my test HTML file does not show in the web browser until I shut down the server process. I see the message being sent by prints in the console, but the web browser keeps loading until the server is stopped. The same instant the server is stopped the page is shown. Why is this?

listener(Listen) ->
  case gen_tcp:accept(Listen) of
    {ok, Client} ->
      case gen_tcp:recv(Client, 0) of
        {ok, Request} ->
          workers:worker({Client, Request});
        {error, closed} ->
          io:format("Socket closed.~n");
        {error, _Reason} ->
          io:format("Error: ~w~n", [_Reason])
      end,
      listener(Listen);
    {error, Error} ->
      io:format("Error ~w~n", [Error]),
      error
  end.

worker({Client, Request}) ->
  {Request_line, Headers, Body} = http_parse:parse_request(Request),
  Response = http_parse:create_response({Request_line, Headers, Body}),
  case gen_tcp:send(Client, Response) of
     ok ->
      io:format("Message sent!~n");
    {error, Reason} ->
      io:format("Could not send packet: ~w~n", [Reason])
  end.

Above is some of the code I've written. I've left the parsing out, but that part works. listener/1 receives a socket created by calling gen_tcp:listen/2 with the options list, {active, false}. Any guidance as of why the page displays only after the server is shut down is appreciated.


Solution

  • The issue is that the response header is missing the Content-Length data.

    Without a Content-Length data, the client assumes that disconnection will mark the end of the data (body) segment.

    Your server never closes the connection (nor does it implement a timeout), so the client is kept waiting for more data (it assumes more data is on it's way).

    Once the connection is closed, the client marks this as the end of the body (data) segment.

    You should consider implementing a timeout as well as managing the response headers for Content-Length, Connection and Keep-Alive.

    Consider learning more about the protocol by reading some of the specs or reading in Wikipedia about the HTTP Protocol and it's headers.