23

So I would like my Rails app instances to register themselves on a "I'm up" kind of thing I'm playing with, and I'd like it to be able to mention what local port it's running on. I can't seem to find how to do it - in fact just finding out its IP is tricky and needs a bit of a hack.

But no problem, I have the IP - but how can I find what port my mongrel/thin/webrick server is running on?

To be super explicit, if I start a rails app using script/server -p 3001, what can I do to pull that 3001 inside the app.

chopper
  • 6,649
  • 7
  • 36
  • 53
RailFan
  • 251
  • 1
  • 4
  • 7
  • Whereabouts are you putting the code which does the registering? – mikej Oct 12 '09 at 12:57
  • I would like it to be in an initializer but it could be anyway really. The important thing is it's able to announce itself to another machine - "hi, i was started on port #{PORT}" - where port could be anything. Basically, Rails equivalent to Sinatra::Application.port. – RailFan Oct 12 '09 at 18:05
  • Most answers to the hostname question also answer this: http://stackoverflow.com/questions/42566/getting-the-hostname-or-ip-in-ruby-on-rails – Ciro Santilli OurBigBook.com Oct 09 '14 at 20:36

6 Answers6

21

You can call Rails::Server.new.options[:Port] to get the port that your Rails server is running on. This will parse the -p 3001 args from your rails server command, or default to port 3000.

ndbroadbent
  • 13,513
  • 3
  • 56
  • 85
15

From inside any controller action, check the content of request.port, thus:

class SomeController < ApplicationController
  def some_action
    raise "I'm running on port #{request.port}."
  end
end
Lars Haugseth
  • 14,721
  • 2
  • 45
  • 49
  • So simple and so easily overlooked. I thought about this for a few minutes and was thinking out round about ways of getting it. This question is a good reminder for me to review request again. http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html – Jim Oct 12 '09 at 14:44
  • Precise for localhost, but does not work when behind an Apache Server or in a cluster setup. – Swanand Oct 12 '09 at 17:28
  • Thanks for the answer. Do you have any idea how to access that programmatically, ie something I can do inside script/console? After all, if I need to access it via HTTP, that means I already know the port! – RailFan Oct 12 '09 at 17:55
11

Two ways.

If you're responding to a request in a controller or view, use the request object:

request.port

If you're in an initialiser and don't have access to the request object use the server options hash:

Rails::Server.new.options[:Port]
superluminary
  • 47,086
  • 25
  • 151
  • 148
  • 3
    `(rdb:1) Rails::Server *** NameError Exception: uninitialized constant Rails::Server` – zuba Mar 06 '14 at 13:20
  • @zuba, that's interesting. Did that occur in your initializer? – superluminary Mar 06 '14 at 13:22
  • Sorry, no, that occured in my controller rspec test debug console – zuba Mar 06 '14 at 17:21
  • 3
    You may have to require the appropriate library first. `require 'rails/commands/server'` – Seth Jeffery Oct 27 '14 at 10:02
  • @SethJeffery, it worked, but i have a little warning: By requiring rails server commands, you can't pass arguments to cucumber/rspec because the rails server launcher will raise an exception claiming that he got wrong arguments. – MhdSyrwan Apr 02 '15 at 09:17
9

I played around with this a bit, and this might be the best solution for Rails 5.1:

Rails::Server::Options.new.parse!(ARGV)[:Port]
jfly
  • 303
  • 3
  • 7
6

Building on the other answers (which saved my bacon!), I expanded this to give sane fallbacks:

In development:

port = Rails::Server::Options.new.parse!(ARGV)[:Port] || 3000 rescue 3000

In all other env's:

port = Rails::Server::Options.new.parse!(ARGV)[:Port] || 80 rescue 80

The rescue 80 covers you if you're running rails console. Otherwise, it raises NameError: uninitialized constant Rails::Server. (Maybe also early in initializers? I forget...)

The || 80 covers you if no -p option is given to server. Otherwise you get nil.

David Hempy
  • 5,373
  • 2
  • 40
  • 68
5

For Rails 5.1 development server.

if Rack::Server.new.options[:Port] != 9292 # rals s -p PORT
  local_port = Rack::Server.new.options[:Port]
else
  local_port = (ENV['PORT'] || '3000').to_i # ENV['PORT'] for foreman
end
hiroshi
  • 6,871
  • 3
  • 46
  • 59