0

I'm trying to implement a module with httpd, which handles HTTP get request for a process. Basically it handles the incoming get request, parses the get parameters and calls a synchronous gen_server method on the node, which started the http server. Then, it returns some HTML with the return values from the synchronous call. All works fine, until I test it with a browser (Chrome, Firefox latest versions working). But I need to implement a HTTP forwarding feature, where the http server can call an other URL with the given parameters. I tried it with httpc:

httpc:request(get, {"http://localhost:55556/httpfront:get?key=1", []}, [], []).

but the following error was thrown:

{error,{failed_connect,[{to_address,{"localhost",55556}},
                        {inet,[inet],econnrefused}]}}

Can you help me out please? What am I missing?

Ps. other sites, such as stackoverflow.com work with the above httpc:request(...).

Config: I start the node.erl, the node starts the httpfront.erl httpd daemon in an other module, the get request is handled at httpfront. I do this several times (start more nodes), now I want to connect from one httpfront instance with httpc:request(...) to an other. All of the HTTP handlers are started at localhost, but different non-proprietary port.

node.erl:

http_listener() ->
    httpfront:start().

start() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
...

httpfront.erl:

start() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []),
%this is the port number, it increments on each new node
    P = 55556,
    % the corresponding url is: http://localhost:port/
    % command are accesible this way:
    % port is from 55556 until end of valid port range, increments on new node join
    % http://localhost:55556/httpfront:get?key=thisisashortkey
    inets:start(),
    inets:start(httpd, [
        {modules, [
            mod_alias, 
            mod_auth, 
            mod_esi, 
            mod_actions, 
            mod_cgi, 
            mod_dir, 
            mod_get, 
            mod_head, 
            mod_log, 
            mod_disk_log
        ]},
        {port,P},
        {server_name,"httpfront"},
        {server_root,"log"},
        {document_root,"www"},
        {erl_script_alias, {"", [httpfront]}},
        {error_log, "error.log"},
        {security_log, "security.log"},
        {transfer_log, "transfer.log"},
        {mime_types,[
            {"html","text/html"}
            ]}
        ]),
        io:format("OK. Good to go.~n").

    get(SessionID, _Env, Input) ->
    % this get() is a gen_server synchronous call on the inside
    Result = node:get(Input),

    mod_esi:deliver(SessionID, [
        "Content-Type: text/html\r\n\r\n", 
        "<html><body>",
        "Get<br>",
        "Key=" ++ Value,
        "<br>Result=" ++ Result,
        "</body></html>"


    ]).
    ...

Now finally I try to call this, as I stated, from an other node, but I get the error:

httpc:request(get, {"http://localhost:55556/httpfront:get?key=1", []}, [], []).
{error,{failed_connect,[{to_address,{"localhost",55556}},
                        {inet,[inet],econnrefused}]}}

Any help and advice is appreciated. Thank you.

balcsok
  • 33
  • 2
  • 11
  • I suspect you're hitting IPv4 vs. IPv6 issues, where `localhost` is resolving to `::1` for your client but your server is listening only on `127.0.0.1`. – Steve Vinoski May 09 '15 at 07:30
  • @SteveVinoski Thank you, I tried it also with `httpc:request(get, {"http://127.0.0.1:55556/httpfront:get?key=1", []}, [], []).`, but the same error occurs. Also, if I start a different web server (a blank project with nginx) on any not occupied port on localhost, the above request works with no problem connecting to that (with localhost in the httpc request). I disabled my antivirus and firewall, but no change. Is this what you were referring to? – balcsok May 09 '15 at 08:37
  • Yes, something like that. It's also possible `httpd` is listening on `::1` but your client is trying `127.0.0.1`. What happens if you have your client try your computer's non-local IP address instead of `localhost`? – Steve Vinoski May 09 '15 at 11:52
  • Same error (`econnrefused`) for my public IP address and the local `192.168.x.x`. Since I'm not familiar with IPv6, I couldn't try `::1` as you suggested. Can you please give an example? Is it possible that it maps to IPv6 for default? I didn't change the `httpd` options. – balcsok May 09 '15 at 11:56
  • Are you sure `httpd` is running where you think it is? Does `netstat -an | grep 55556` show that port in TCP listen mode for all interfaces? – Steve Vinoski May 09 '15 at 12:04
  • Since I'm on windows, I tried `netstat -an | findstr 55556`, this shows the following: `TCP [::]:55555 [::]:0 LISTENING`. What is this supposed to mean? It's listening on TCP only, on port 55555, but what exactly is [::]? – balcsok May 09 '15 at 12:36
  • EDIT: for comparison, the nginx server is running on port `8080`, netstat shows this: `TCP 127.0.0.1:8080 0.0.0.0:0 LISTENING`. The `httpc` is able to connect to this server, so the devil will be in the configuration, but I have no idea how to set up my `httpd` so it is bound to an IP (Google fails for me). But why does it work from the browser then? :) – balcsok May 09 '15 at 12:42
  • Sorry I messed up the port numbers up there in `findstr`. All ports are 55555 in that comment. – balcsok May 09 '15 at 13:23

1 Answers1

0

Try passing {ipfamily, inet} as a member of the option list for your httpd start call to get it to listen on IPv4 instead of IPv6. Also, since you likely want only localhost connectivity, you might consider passing the {bind_address, {127,0,0,1}} option as well.

Steve Vinoski
  • 19,847
  • 3
  • 31
  • 46