<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-text-flowed" style="font-family: -moz-fixed;
      font-size: 12px;" lang="x-unicode">Hi,
      <br>
      <br>
      I have a problem with gen_tcp:recv...
      <br>
      The Body of the first call is missing but shows up at the second
      call causing a http_error. (full code is shown a the end of the
      mail)
      <br>
      <br>
      I do a gen_tcp:connect/4 with the options
      <br>
      [list, {mode, list}, {reuseaddr, true}, {active, false},
      {keepalive, true}, {packet, http}, {send_timeout,
      timer:seconds(2)}]
      <br>
      <br>
      Then i send a HTTP POST request using gen_tcp:send/2 and go into a
      "receve loop" with gen_tcp:recv/3 until i get a {error,_}  (thats
      for debugging at the moment and recv timout is set to 10 seconds)
      <br>
      <br>
      my problem is:
      <br>
      - On the first call (send) i get all the headers but no content.
      <br>
      - On the second call i get the content of the first call at the
      beginning of the response causing the http_error.
      <br>
      <br>
      <br>
      I'm sending the request to a node.js service, but the result is
      the same if i use a dummy apache service with the same response.
      <br>
      So i don't think its a problem with the Server I'm sending the
      request to.
      <br>
      The Body of the response (aka content) is always "OK"
      <br>
      <br>
      The received data from the first call looks like this (there is no
      body with "OK", it ends with http_eoh and then a timeout after 10
      seconds) :
      <br>
      <br>
       {ok,{http_response,{1,1},200,"OK"}}
      <br>
       {ok,{http_header,0,"X-Powered-By",undefined,"Express"}}
      <br>
       {ok,{http_header,42,'Content-Type',undefined,"text/html;
      charset=utf-8"}}
      <br>
       {ok,{http_header,38,'Content-Length',undefined,"2"}}
      <br>
       {ok,{http_header,3,'Date',undefined,"Tue, 10 Mar 2015 20:23:05
      GMT"}}
      <br>
       {ok,{http_header,2,'Connection',undefined,"keep-alive"}}
      <br>
       {ok,http_eoh}
      <br>
          ...after 10 seconds...
      <br>
       {error,timeout}
      <br>
      <br>
      The second call then returns this (notice the OKHTTP/1.1... in the
      first row, "OK" is the Body from the call before. It should be
      HTTP/1.1):
      <br>
      <br>
       {ok,{http_error,"OKHTTP/1.1 200 OK\r\n"}}
      <br>
       {ok,{http_error,"X-Powered-By: Express\r\n"}}
      <br>
       {ok,{http_error,"Content-Type: text/html; charset=utf-8\r\n"}}
      <br>
       {ok,{http_error,"Content-Length: 2\r\n"}}
      <br>
       {ok,{http_error,"Date: Tue, 10 Mar 2015 20:23:16 GMT\r\n"}}
      <br>
       {ok,{http_error,"Connection: keep-alive\r\n"}}
      <br>
       {ok,{http_error,"\r\n"}}
      <br>
          ...after 10 seconds...
      <br>
       {error,timeout}
      <br>
      <br>
      <br>
      <br>
      here is the gen_server code im using for my tests.
      <br>
      i run the test like this from the erl command line
      <br>
      s:start_link().
      <br>
      s:work(1,1). % first call without body
      <br>
      s:work(1,1). % second call that fails
      <br>
      <br>
      Thanky for your help!
      <br>
      <br>
      <br>
%%%-------------------------------------------------------------------
      <br>
      %%% @author mlersch
      <br>
      %%% @copyright (C) 2015, <COMPANY>
      <br>
      %%% @doc
      <br>
      %%%
      <br>
      %%% @end
      <br>
      %%% Created : 20. Feb 2015 11:13
      <br>
%%%-------------------------------------------------------------------
      <br>
      -module(s).
      <br>
      -author("mlersch").
      <br>
      <br>
      %% API
      <br>
      -compile(export_all).
      <br>
      <br>
      -behaviour(gen_server).
      <br>
      <br>
      %% API
      <br>
      -export([
      <br>
        start_link/0,
      <br>
        send/2,
      <br>
        reconnect/4]).
      <br>
      <br>
      %% gen_server callbacks
      <br>
      -export([init/1,
      <br>
        handle_call/3,
      <br>
        handle_cast/2,
      <br>
        handle_info/2,
      <br>
        terminate/2,
      <br>
        code_change/3]).
      <br>
      <br>
      -define(SERVER, ?MODULE).
      <br>
      <br>
      -record(state, {
      <br>
        connection=false,
      <br>
        host,
      <br>
        port,
      <br>
        timeout,
      <br>
        opts
      <br>
      }).
      <br>
      <br>
      <br>
%%%===================================================================
      <br>
      %%% API
      <br>
%%%===================================================================
      <br>
      <br>
      send(Processor, Data)->
      <br>
        gen_server:call(?MODULE, {send, Processor, Data}).
      <br>
      <br>
      info()->
      <br>
        gen_server:call(?MODULE,info).
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @doc
      <br>
      %% Starts the server
      <br>
      %%
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(start_link() ->
      <br>
        {ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
      <br>
      start_link() ->
      <br>
        process_flag(trap_exit, true),
      <br>
        io:format("~p Start~n",[?MODULE]),
      <br>
        gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
      <br>
      <br>
%%%===================================================================
      <br>
      %%% gen_server callbacks
      <br>
%%%===================================================================
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% Initializes the server
      <br>
      %%
      <br>
      %% @spec init(Args) -> {ok, State} |
      <br>
      %%                     {ok, State, Timeout} |
      <br>
      %%                     ignore |
      <br>
      %%                     {stop, Reason}
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(init(Args :: term()) ->
      <br>
        {ok, State :: #state{}} | {ok, State :: #state{}, timeout() |
      hibernate} |
      <br>
        {stop, Reason :: term()} | ignore).
      <br>
      init([]) ->
      <br>
      <br>
        State = #state{
      <br>
          host = "localhost",
      <br>
          port = 9010,
      <br>
          timeout = timer:seconds(2),
      <br>
          opts = [list, {mode, list}, {reuseaddr, true}, {active, true},
      {keepalive, true}, {packet, http}, {send_timeout,
      timer:seconds(2)}]
      <br>
        },
      <br>
      <br>
        reconnect(State),
      <br>
        {ok, State}.
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% Handling call messages
      <br>
      %%
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(handle_call(Request :: term(), From :: {pid(), Tag ::
      term()},
      <br>
          State :: #state{}) ->
      <br>
        {reply, Reply :: term(), NewState :: #state{}} |
      <br>
        {reply, Reply :: term(), NewState :: #state{}, timeout() |
      hibernate} |
      <br>
        {noreply, NewState :: #state{}} |
      <br>
        {noreply, NewState :: #state{}, timeout() | hibernate} |
      <br>
        {stop, Reason :: term(), Reply :: term(), NewState :: #state{}}
      |
      <br>
        {stop, Reason :: term(), NewState :: #state{}}).
      <br>
      <br>
      handle_call({send, Processor, Data}, From, State) ->
      <br>
      <br>
        % If we are offline, notify the caller
      <br>
        case State#state.connection of
      <br>
      <br>
          {ok,Con}->
      <br>
      <br>
            Request =
      <br>
              ["POST /" ++ Processor ++ " HTTP/1.1\r\n"
      <br>
                ++ "Content-Length: " ++
      integer_to_list(lists:flatlength(Data)) ++ "\r\n"
      <br>
                ++ "User-Agent: Erlang Client\r\n"
      <br>
                ++ "Content-Type: application/json\r\n"
      <br>
                ++ "Host: " ++ State#state.host ++ "\r\n"
      <br>
                ++ "Accept: */*\r\n"
      <br>
                ++ "\r\n", [Data]],
      <br>
      <br>
              % Try sending the data
      <br>
              case send_and_receive(Con, Request) of
      <br>
                ok -> {reply, ok, State};
      <br>
      <br>
                % If sending fails...
      <br>
                Error ->
      <br>
                  % ...Answer the Client with a error
      <br>
                  gen_server:reply(From, error),
      <br>
                  io:format("~p Error: ~p~n", [?MODULE, Error]),
      <br>
      <br>
                  % ...Close the connection
      <br>
                  gen_tcp:close(Con),
      <br>
                  timer:sleep(500),
      <br>
      <br>
                  % ...Spawn a Process that trys to reconnect.
      <br>
                  reconnect(State),
      <br>
      <br>
                  % ...Update the connection state
      <br>
                  {reply, error, State#state{connection = false}}
      <br>
      <br>
              end;
      <br>
      <br>
            _ -> {reply, offline, State}
      <br>
        end;
      <br>
      <br>
      handle_call(info, _From, State) ->
      <br>
        {reply, State, State};
      <br>
      <br>
      handle_call(Request, _From, State) ->
      <br>
        io:format("~p CALL: ~p~n", [?MODULE, Request]),
      <br>
        {reply, ok, State}.
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% Handling cast messages
      <br>
      %%
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(handle_cast(Request :: term(), State :: #state{}) ->
      <br>
        {noreply, NewState :: #state{}} |
      <br>
        {noreply, NewState :: #state{}, timeout() | hibernate} |
      <br>
        {stop, Reason :: term(), NewState :: #state{}}).
      <br>
      handle_cast({connected, Connection}, State) ->
      <br>
        io:format("~p Connected: ~p~n", [?MODULE, Connection]),
      <br>
        {noreply, State#state{connection = Connection}};
      <br>
      <br>
      handle_cast(Request, State) ->
      <br>
        io:format("~p CAST: ~p~n", [?MODULE, Request]),
      <br>
        {noreply, State}.
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% Handling all non call/cast messages
      <br>
      %%
      <br>
      %% @spec handle_info(Info, State) -> {noreply, State} |
      <br>
      %%                                   {noreply, State, Timeout} |
      <br>
      %%                                   {stop, Reason, State}
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(handle_info(Info :: timeout() | term(), State :: #state{})
      ->
      <br>
        {noreply, NewState :: #state{}} |
      <br>
        {noreply, NewState :: #state{}, timeout() | hibernate} |
      <br>
        {stop, Reason :: term(), NewState :: #state{}}).
      <br>
      <br>
      handle_info({tcp_closed, _}, State) ->
      <br>
        io:format("~p Connection closed!~n", [?MODULE]),
      <br>
        reconnect(State),
      <br>
        {noreply, State#state{connection = false}};
      <br>
      <br>
      handle_info(Info, State) ->
      <br>
        io:format("~p INFO: ~p~n", [?MODULE, Info]),
      <br>
        {noreply, State}.
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% This function is called by a gen_server when it is about to
      <br>
      %% terminate. It should be the opposite of Module:init/1 and do
      any
      <br>
      %% necessary cleaning up. When it returns, the gen_server
      terminates
      <br>
      %% with Reason. The return value is ignored.
      <br>
      %%
      <br>
      %% @spec terminate(Reason, State) -> void()
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(terminate(Reason :: (normal | shutdown | {shutdown, term()}
      | term()),
      <br>
          State :: #state{}) -> term()).
      <br>
      terminate(Reason, _State) ->
      <br>
        io:format("~p TERMINATE: ~p~n", [?MODULE, Reason]),
      <br>
        ok.
      <br>
      <br>
%%--------------------------------------------------------------------
      <br>
      %% @private
      <br>
      %% @doc
      <br>
      %% Convert process state when code is changed
      <br>
      %%
      <br>
      %% @spec code_change(OldVsn, State, Extra) -> {ok, NewState}
      <br>
      %% @end
      <br>
%%--------------------------------------------------------------------
      <br>
      -spec(code_change(OldVsn :: term() | {down, term()}, State ::
      #state{},
      <br>
          Extra :: term()) ->
      <br>
        {ok, NewState :: #state{}} | {error, Reason :: term()}).
      <br>
      code_change(_OldVsn, State, _Extra) ->
      <br>
        {ok, State}.
      <br>
      <br>
%%%===================================================================
      <br>
      %%% Internal functions
      <br>
%%%===================================================================
      <br>
      <br>
      <br>
      <br>
      %% This helper function sends the request to the server and parses
      the response
      <br>
      %% to look in it for a status 200 code. If it finds a 200 we
      return ok otherwise error.
      <br>
      %% by default we use active connections, when we are in idle to
      get info messages about
      <br>
      %% deconnections into handle_info/2
      <br>
      %% but here we must change to passive mode, so we are able to
      parse the response of this
      <br>
      %% send operations. disconnect messages wont show up in passive
      mode but will pop up when
      <br>
      %% we switch bach to active mode again (even if the ocured during
      passive mode).
      <br>
      send_and_receive(Con, Request)->
      <br>
        inet:setopts(Con, [{active, false}]),
      <br>
        Response =
      <br>
        case gen_tcp:send(Con, Request) of
      <br>
          ok -> parse_response(Con);
      <br>
          E -> E
      <br>
        end,
      <br>
        inet:setopts(Con, [{active, true}]),
      <br>
        Response.
      <br>
      <br>
      <br>
      parse_response(Con)->parse_response(Con, error).
      <br>
      parse_response(Con, State)->
      <br>
        R = gen_tcp:recv(Con, 0, timer:seconds(10)),
      <br>
        io:format("PR: ~p~n",[R]),
      <br>
        case R of
      <br>
          {ok,{http_response,_,200,_}} -> parse_response(Con, ok);
      <br>
          {ok,http_eoh} ->
      <br>
            io:format("PRX: ~p~n",[gen_tcp:recv(Con, 0,
      timer:seconds(10))]),
      <br>
            State;
      <br>
          {error, E} -> {error, E};
      <br>
          _ -> parse_response(Con, State)
      <br>
        end.
      <br>
      <br>
      reconnect(State)->
      <br>
        spawn_link(?MODULE, reconnect, [self(), State,
      calendar:local_time(), 1]).
      <br>
      <br>
      reconnect(Pid, State, Started, Tries)->
      <br>
        io:format("~p Connecting to host ~p on port ~p~n",[?MODULE,
      State#state.host, State#state.port]),
      <br>
        case gen_tcp:connect(State#state.host, State#state.port,
      State#state.opts, State#state.timeout) of
      <br>
          {ok, Connection} ->
      <br>
            io:format("~p Reconnect changing controlling process:
      ~p~n",[?MODULE, gen_tcp:controlling_process(Connection, Pid)]),
      <br>
            gen_server:cast(?MODULE, {connected, {ok, Connection}});
      <br>
          E -> io:format("~p Reconnection failed ~p (Tried it ~p
      times since ~p). Waiting 2sec. till retry!~n", [?MODULE, E, Tries,
      Started]),
      <br>
               timer:sleep(timer:seconds(2)),
      <br>
               reconnect(Pid, State, Started, Tries+1)
      <br>
        end.
      <br>
      <br>
      <br>
      <br>
%%%===================================================================
      <br>
      %%% Debug stuff
      <br>
%%%===================================================================
      <br>
      loop(Max)->
      <br>
        lists:foreach(fun(_)->
      <br>
          timer:sleep(100),
      <br>
            spawn(fun()->
      <br>
              send("processgaac",
      "{\"_id\":{\"$oid\":\"53B382F4BE53EE3946137430\"},\"sid\":\"07101a57ce294750bb36fa72e2ffab5d\",\"eid\":1566,\"cd\":{\"$date\":1404273396000},\"t\":\"gaac\",\"p\":{\"ua\":\"Mozilla/5.0

      (Windows NT 6.3; WOW64; rv:30.0) Gecko/20100101
Firefox/30.0\",\"pt\":\"search_result\",\"rt\":\"internal\",\"gs\":[{\"g\":\"08006309\",\"p\":1650},{\"g\":\"04431464\",\"p\":1429},{\"g\":\"03932773\",\"p\":696},{\"g\":\"07563999\",\"p\":825},{\"g\":\"09100275\",\"p\":5089},{\"g\":\"06426800\",\"p\":2240},{\"g\":\"10417853\",\"p\":1180},{\"g\":\"02096458\",\"p\":1365},{\"g\":\"08798173\",\"p\":3897},{\"g\":\"03531850\",\"p\":1243},{\"g\":\"00188357\",\"p\":412},{\"g\":\"09296203\",\"p\":2495},{\"g\":\"05566143\",\"p\":1498},{\"g\":\"08006456\",\"p\":1467},{\"g\":\"04347717\",\"p\":2199},{\"g\":\"08006410\",\"p\":4499},{\"g\":\"09374110\",\"p\":3897},{\"g\":\"04187656\",\"p\":691},{\"g\":\"05010397\",\"p\":1075},{\"g\":\"07727923\",\"p\":493}],\"cats\":[\"1100068\",\"1100068\",\"1100068\",\"1100071\",\"1100043\",\"1100015\",\"1100015\",\"1100029\",\"1100355\",\"1100355\",\"1100196\",\"1100114\",\"1100013\",\"1100021\",\"1100021\",\"1100021\",\"1100021\",\"1100021\",\"1100170\",\"1571\",\"1100014\",\"1100117\",\"1100233\",\"1100107\",
\"1100096\",\"1100467\",\"1100094\",\"1100094\",\"1100013\",\"1100014\",\"1100014\",\"1100029\",\"1100015\",\"1100015\",\"1100017\",\"1100463\",\"1100034\",\"1100109\",\"1440\",\"1100114\",\"1100109\",\"1440\",\"1100177\",\"1100013\",\"1100191\",\"1100094\",\"1100191\",\"1100029\",\"1100029\",\"1100048\",\"1100043\",\"1100016\",\"1100210\",\"1100016\",\"1100463\",\"1226\"],\"catsc\":[\"AR02AA16\",\"79680\",\"22172\",\"30365\",\"AR01AC03\",\"24009\",\"79658\",\"66403\",\"30365\",\"22294\",\"BX01\",\"71445\",\"81085\",\"24510\",\"30365\",\"22294\",\"AD11AX01\",\"82323\",\"30365\",\"22294\",\"30365\",\"22294\",\"BB03Z\",\"81644\",\"81629\",\"25123\",\"22183\",\"22182\",\"30365\",\"30365\",\"BB01A\",\"24577\",\"66407\",\"30365\",\"AD01AE16\",\"30365\",\"AD08AC\",\"24512\",\"22206\",\"30365\",\"AN05CX\",\"81736\",\"22192\",\"30365\",\"BB03Z\",\"77677\",\"66409\",\"66407\",\"30365\",\"BX01\",\"71446\",\"79609\",\"22171\",\"30365\",\"BC01D\",\"30365\",\"BB03D\",\"82323\",\"25125\",\"22204\",
\"30365\",\"22294\",\"AD11AX01\",\"82997\",\"82323\",\"25125\",\"22204\",\"32455\",\"30365\",\"22294\",\"BB03Z\",\"24783\",\"81736\",\"81083\",\"81082\",\"81087\",\"39604\",\"30365\",\"AS01GX07\",\"24009\",\"22220\",\"22196\",\"79610\",\"30365\",\"22294\",\"BC01D\",\"24728\",\"30365\",\"23432\",\"30365\"],\"catsx\":[\"30365\",\"30365\",\"22294\",\"30365\",\"22294\",\"82323\",\"30365\",\"22294\",\"30365\",\"22294\",\"30365\",\"30365\",\"30365\",\"30365\",\"30365\",\"30365\",\"77677\",\"30365\",\"30365\",\"30365\",\"82323\",\"30365\",\"22294\",\"82997\",\"82323\",\"30365\",\"22294\",\"39604\",\"30365\",\"30365\",\"22294\",\"30365\",\"23432\",\"30365\"],\"fpid\":\"/aktionsartikel\",\"lt\":\"list\",\"lp\":1},\"r\":{\"s\":[{\"slid\":\"high\",\"cid\":2498,\"scr\":100000000,\"f\":1}]},\"ti\":200000000,\"to\":false,\"at\":53596,\"dv\":8,\"agg\":[],\"pad\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"}")<br>
            end)
      <br>
          end,
      <br>
          lists:seq(1,Max)).
      <br>
      <br>
      work(Loops, Max)->
      <br>
        lists:foreach(fun(_)-> spawn(s,loop,[Max])
      end,lists:seq(1,Loops)).
      <br>
      <br>
      <div class="moz-txt-sig"><span class="moz-txt-tag">-- <br>
        </span>________________________________________
        <br>
        Matthias Lersch, Senior Software Architect
        <br>
        Tel.: +49 69 972 69 197; Fax: +49 69 972 69 204; Email: <a
          class="moz-txt-link-abbreviated"
          href="mailto:matthias.lersch@kairion.de">matthias.lersch@kairion.de</a>
        <br>
        Kairion GmbH, Gutleutstraße 30, D-60329 Frankfurt
        <br>
        Internet: <a class="moz-txt-link-freetext"
          href="http://www.kairion.de">http://www.kairion.de</a>
        <br>
        <br>
        <br>
      </div>
    </div>
  </body>
</html>