Skip to content

Instantly share code, notes, and snippets.

@indiesquidge
Created January 19, 2016 07:42
Show Gist options
  • Save indiesquidge/b836647f851179589765 to your computer and use it in GitHub Desktop.
Save indiesquidge/b836647f851179589765 to your computer and use it in GitHub Desktop.
how to access subdomains locally with Rails 5

Subdomaining Localhost with Rails 5

I've been following this blog post on how to set up an api-only Rails 5 application. One of the sections talks about creating a subdomain for your api

Rails.application.routes.draw do
  constraints subdomain: "api" do
    scope module: "api" do
      namespace :v1 do
        resources :users
      end
    end
  end
end

So that you can have namespacing and versioning like

http://api.my-website.com/v1/users

However, this seems to cause some issues locally. At first I just kept getting back a 404 error that the route I was searching for didn't exist despite it showing up correctly when I ran rake routes

  Prefix Verb   URI Pattern             Controller#Action
v1_users GET    /v1/users(.:format)     api/v1/users#index {:subdomain=>"api"}
         POST   /v1/users(.:format)     api/v1/users#create {:subdomain=>"api"}
 v1_user GET    /v1/users/:id(.:format) api/v1/users#show {:subdomain=>"api"}
         PATCH  /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
         PUT    /v1/users/:id(.:format) api/v1/users#update {:subdomain=>"api"}
         DELETE /v1/users/:id(.:format) api/v1/users#destroy {:subdomain=>"api"}

Removing constraints subdomain: "api" gave back the correct response, allowing me to prove to myself that this was indeed the issue.

Attempted solutions

  1. Editing /etc/hosts and adding in my subdomain to map to 127.0.0.1

As your machine gets started, it will need to know the mapping of some hostnames to IP addresses before DNS can be referenced. This mapping is kept in the /etc/hosts file. In the absence of a name server, any network program on your system consults this file to determine the IP address that corresponds to a host name.

I had seen a few forums that mentioned this as a solution, so I added this to /etc/hosts

127.0.0.1	api.dev.local

When I went to http://http://api.dev.local:3000/ all I got back from Chrome was

ERR_CONNECTION_REFUSED

Trying this URL on Firefox and Safari resulted in the same thing (Safari never ended up actually giving that error, it just "loaded" the page indefinitely).

  1. Using lvh.me and xip.io

I think this started with Tim Pope's invention of smackaho.st, which was simply a public domain pointed at 127.0.0.1 (localhost). lvh.me and xip.io are just spawns of that same idea since both are shorter and less offensive.

Unfortunately, lvh.me returns the same connection refused error as mentioned above and xip.io hangs indefinitely.

  1. Changing proxy settings in Chrome to include localhost and lvh.me

Since I'm getting ERR_CONNECTION_REFUSED and not ERR_EMPTY_RESPONSE as would be expected if the domain wasn't working, I figured this was some sort of security check put in place by Chrome (and probably on Firefox and Safari too).

I tried ignoring the proxy settings for localhost, lvh.io, and xip.io as per this Stack Overflow answer. Nothing changed; I continued getting the same connection error.

Solution

config.action_dispatch.tld_length sets the TLD (top-level domain) length for the application. Defaults to 1.

Setting config.action_dispatch.tld_length = 0 in config/environments/development.rb. Simple as that. This works, although I am unsure of any unseen consequences with testing and cookies in, as is noted upon in the answer.

Resources:

If there is something you notice I am doing wrong, something you would like to add, or some question you may have, please feel free to comment on this post :)

@rmonteiro89
Copy link

Thank you! It worked! =)

Did you find any downside with this solution?

@aalvrz
Copy link

aalvrz commented Sep 11, 2016

This ended so many hours of pain and suffering. Thank you so much!

@jjensn
Copy link

jjensn commented Oct 22, 2016

Cheers thanks for this post

@gudongfeng
Copy link

amazing! it worked!

@JBFowler
Copy link

👍 Thank you sir!

@hendricius
Copy link

In my case the issue was I used a symbol for the subdomain. When using string syntax, it worked :).

@Wynandstolp
Copy link

Thanks, I initially had 127.0.0.1 some.thing.localhost which didn't work. Changing to 127.0.0.1 some.thing.local did the trick.

@NateJBeck
Copy link

Works like a charm - thanks!

@viphat
Copy link

viphat commented Jul 21, 2017

:(, Your solution costs me half of a day. When I revert back to config.action_dispatch.tld_length = 1, it works again.

@gSanchezCiarrocchi
Copy link

Great!

@t56k
Copy link

t56k commented Mar 26, 2018

This worked great. Thank-you so much.

@myusufid
Copy link

myusufid commented Nov 1, 2018

thank you sir

@clementinoux
Copy link

<3

@jtopgi
Copy link

jtopgi commented Mar 19, 2019

👍
You can now add your subdomain in front of localhost:3000 and it should work.

@MusaAbdillah
Copy link

and now i can access subdomain like http://staging-dashboard.localhost:3000/dashboard/products. thanks for save my day!

@kbdjuve
Copy link

kbdjuve commented Aug 11, 2020

Thank you!

@Piyush-Chaudhary
Copy link

Thanks, brother. Worked.

@mzmt
Copy link

mzmt commented Sep 25, 2020

Thank you!

If you write this, admin.localhost:3000/profile will return users#profile in spite of admin subdomain.

Rails.application.routes.draw do
  constraints subdomain: 'admin' do
    get 'login' => 'user_sessions#new'
  end

  get 'login' => 'user_sessions#new'
  get 'profile' => 'users#profile'
end

So, if you want to match only admin subdomain, you can write this.

Rails.application.routes.draw do
  constraints subdomain: 'admin' do
    get 'login' => 'user_sessions#new'
  end

  constraints subdomain: '' do
    get 'login' => 'user_sessions#new'
    get 'profile' => 'users#profile'
  end
end

@vin-droid
Copy link

I added the same as you did.
127.0.0.1 api.dev.local
127.0.0.1 www.api.dev.local

Now I am running my rails server to port 80.
rvmsudo rails server -p 80

Everything is working fine, no needed any other lib.
http://www.www.api.dev.local

@yashka713
Copy link

You save my day ❤️
Many Cheers!

Setting config.action_dispatch.tld_length = 0 in config/environments/development.rb

@shrihari007
Copy link

Thanks this worked

Setting config.action_dispatch.tld_length = 0 in config/environments/development.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment