quda

quda

Plug Cowboy - Search dynamically for a free port to run the server

I am building a simple http server using Plug.Cowboy (no Phoenix pls!) to serve a json API for a customer. A microservice.
The problem is the customer has a complex environment with multiple services of many sorts, containers, microservices etc. that are serving on various ports in his server. Therefore we were requested to develop the service to look dynamically and launch itself on a free/unused port.
When we build the Elixir app it is requested to declare the port at Plug initialization or it defaults to 4000/4040:

 def start(_type, _args) do
    children = [
      {Plug.Cowboy, scheme: :http, plug: MyApp, port: 1234}
    ]
 ...

How can I re-factory this to search the first available unused port in a certain range ?

Thanks in advance,
Q.T.

Marked As Solved

dodo

dodo

You could probably use Erlang -- gen_tcp (not tested):

def start(_type, _args) do
  children = [
    {Plug.Cowboy, scheme: :http, plug: MyApp, port: get_free_port(4000)}
  ]
  ...
end

defp get_free_port(start) do
  case :gen_tcp.listen(start, [:binary]) do
    {:ok, socket} ->
      :ok = :gen_tcp.close(socket)
      start

    {:error, :eaddrinuse} ->
      get_free_port(start + 1)
  end
end

Also Liked

joey_the_snake

joey_the_snake

If you put port: 0 it seems to look for an available port and use it. I’m not sure if this is safe to be counted on though. I tried it out because in erlang gen_tcp.listen finds an available port when you set port to 0.

hauleth

hauleth

Just beware that this solution is susceptible to TOCTOU.

Nicd

Nicd

It should be safe at least on Linux, see the source: linux/inet_connection_sock.c at 38f80f42147ff658aff218edb0a88c37e58bf44f · torvalds/linux · GitHub

This seems to be a Unix convention of getting a random available port. If you then need to know what port you got, possibly you can dig at the Cowboy socket to gain that information.

hauleth

hauleth

You cannot limit range, but as other have said, using port 0 will give you random port from ephemeral range (configured by the OS). The problem though is how to later extract that port from within your application (it is not done automatically for you).

However using ephemeral ports for listening with your services is a little bit weird, what exactly you are trying to accomplish?

LostKobrakai

LostKobrakai

You could just try listing on a port with the actual server, if it doesn’t fail your there. No separation between checking and using.

Where Next?

Popular in Questions Top

Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
Fl4m3Ph03n1x
Background Let’s assume I have a typical GenServer that receives messages as requests, does some operation in a DB and returns responses....
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
kostonstyle
Hi all I want to have a unix time, from the current time plus 1 hour. DateTime.now + 1 hour How to get it in elixir? Thanks
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

We're in Beta

About us Mission Statement