Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save remon/c3fcd5b9fa96025e69b4f3cf79c7420a to your computer and use it in GitHub Desktop.
Save remon/c3fcd5b9fa96025e69b4f3cf79c7420a to your computer and use it in GitHub Desktop.

Revisions

  1. Austin Wood created this gist Jan 19, 2016.
    105 changes: 105 additions & 0 deletions subdomain-localhost-rails-5.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,105 @@
    # Subdomaining Localhost with Rails 5

    I've been following [this](http://sourcey.com/building-the-prefect-rails-5-api-only-app/)
    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

    ```rb
    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

    ```sh
    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`

    ```rb
    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`

    ```sh
    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](http://i.imgur.com/clCNNvZ.jpg)

    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).

    2. 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](http://tbaggery.com/2010/03/04/smack-a-ho-st.html).

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

    3. 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](http://stackoverflow.com/questions/7227845/localhost-not-working-in-chrome-and-firefox)
    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](http://stackoverflow.com/questions/20095318/rails-4-subdomain-routing).
    This works, although I am unsure of any unseen consequences with testing and
    cookies in, as is noted upon in the answer.

    Resources:
    - http://www.chrisaitchison.com/2013/03/17/testing-subdomains-in-rails/
    - http://stackoverflow.com/questions/7227845/localhost-not-working-in-chrome-and-firefox
    - http://railscasts.com/episodes/221-subdomains-in-rails-3
    - http://stackoverflow.com/questions/20095318/rails-4-subdomain-routing

    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 :)