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

freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
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
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
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
Codball
Mix format works fine if run from the cmd. I’ve followed this to facilitate the implementation into VSC which involves downloading an ext...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
yawaramin
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement