Search code examples
rubysocketsportsinatra

How to programmatically get Sinatra's active port?


I'm creating a simple and portable web application with Sinatra on Ruby, and I'm letting the system find an open port for the server to use with the following:

require 'sinatra'
require 'socket'

socket = Socket.new(:INET, :STREAM, 0)
socket.bind(Addrinfo.tcp("127.0.0.1", 0))

port = socket.local_address.to_s.chomp("\x0").to_i

set :port, port
set :bind, "127.0.0.1"

get "/" do
    "Hello, World!"
end

I'd like to launch the browser to view the application automatically, but the problem is that both the port variable and Sinatra's settings.port are set to 0, so I can't get the URL of the server.

The launch code comes after get "/" do block:

Thread.new do
    system "chromium-browser " <<
        "-app='http://127.0.0.1:#{port}' " <<
        "--no-sandbox > /dev/null 2>&1"
end

After the system starts, I can see the port in the WEBrick output, but how can I get the port that the system assigns to the socket beforehand?


Solution

  • Try this

    require 'sinatra'
    require 'socket'
    
    socket = Socket.new(:INET, :STREAM, 0)
    socket.bind(Addrinfo.tcp("127.0.0.1", 0))
    
    port = socket.local_address.ip_port
    socket.close
    
    set :port, port
    set :bind, "127.0.0.1"
    
    get "/" do
        "Hello, World!"
    end
    

    socket.local_address.ip_port would give you the port info, but you need to close that socket before starting sinatra or it will fail with Errno::EADDRINUSE