Hi!
In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir?
Searched the docs for ip address and the web, no good results.
Thanks!
Hi!
In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir?
Searched the docs for ip address and the web, no good results.
Thanks!
Maybe you can use System.cmd (and ifconfig in linux)?
http://elixir-lang.org/docs/stable/elixir/System.html
hmm, there must be a native method for that?
Elixir does not have builtin web server. If you are using Phoenix, you can try MyApp.Endpoint.url
function. Otherwise check documentation of a webserver.
sysashi, thank you for that information, however I was asking for how to get the current ip address of the server and do not see how your answer is connected to that?
btw what is running when I do mix phoenix.server or run a release?
If it’s not there and you find it should you could try to write it yourself (good exercise! and add it to the language. It’s opensource.
Try to call the erlang function :inet.getif()
If you want to have your app to know about a specific IP, then hardcode it or set it as a config.
It may be possible that you end up in an environment that has multiple interfaces and as such multiple IPs, even worse if your apps server listens on at least two of them. Which IP do you want to know in this setting?
Something like this should do the trick
{:ok, ifs} = :inet.getif()
ips = Enum.map(ifs, fn {ip, _broadaddr, _mask} -> ip end)
I think getif
is not documented, so technically it could disappear eventually. getifaddrs
may be a more future-proof option. Note in practice this will return multiple IPs since you’ll have at least a loopback and an external IP.
You’ll find more options if you google something like “erlang get ip”, whatever works in Erlang will also work in Elixir.
so PHP: $SERVER['SERVERADDR']
in OP’s example will return an IP address of a underlying WEB server, :inet.getif()
will return interfaces on a machine where hypothetically you run you WEB server. Not sure if we all talking about the same stuff
My question is of course related to the exact situation you describe and I would like to see to which IP address phoenix binds automatically and why this happens.
Of course the goal is to have some control over this and I would like to tell phoenix to bind to a specific ip address, do you know how to do that, seems like this is not explicitely documented anywhere. Please see my other question about that from today, thanks!
thank you Stefan for that suggestion, this is a very good idea!
I wish you a very nice sunday, too!
Cowboy does bind to 0.0.0.0 (aka all interfaces) per default and cowboy is the web server used by phoenix.
As I already mentioned in How to bind phoenix app to specific ip address? you can of course change the IP to bind to. And as you can set a config, you can ask for its value as well.
you are right, sysasi - I should have asked more detailed, so really everybody can understand it!
So to be very exact I would like to get the IP address to which phoenix binds to automatically when it is run, I jsut wanted to add a quick debug statement in my template for this, but then it turns out that it evolves into a major task.
Of course in the end it is much more important to be able to bind phoenix to a specific ip address, please see my other question about that from today, thank you very much!
If anyone else is looking for it’s own IP address and finds this thread… In my nerves project I use :inet.getif/0
and loop through the result until I find one that fits my pattern (e.g. one that starts with 192.168).
Just a side note: If you cannot get your “real world” IP with :inet.getif/0
, then you might want to consider making a HTTP-Request to https://httpbin.org/ip, which simply returns your request-IP.
A way to make a good guess at your server IP. (It might not be your public IP if you have NAT). Sadly I couldn’t find a way for erlang to return a list of the network routes, so I had to fall back to a System.cmd call. The idea is find the default gateway for the server, see what dev (interface) it us using, then find the IP addr of that device.
I promise there are better ways to do this that will work with ipv6, not rely on a System.cmd (like read /proc), handle multiple IPs assigned to the same device, etc… but its’ quick and dirty and works for me.:
# Get the name of the default interface (IF)
# Wish erlang hand a command to nicely get the route information
# Could work with `netstat -rn` too with some changes to the regex
{result, 0} = System.cmd("ip", ["route","list","default"])
default_if = Regex.scan(~r/.*dev (.*) .*/U, result, capture: :all_but_first) |> List.first |> List.first |> String.to_charlist
# Now find the default device in the list of all devices
{:ok, ifs} = :inet.getifaddrs
{_if, attrs} = List.keyfind(ifs, default_if, 0)
# Now grab the IP in {a,b,c,d} format
{:addr, ip} = List.keyfind(attrs, :addr, 0)
# Now make it a string (sorry, binary BitString.. whatever)
{a,b,c,d} = ip
"#{a}.#{b}.#{c}.#{d}"