API subdomain for Heroku app, is it possible? - api

I am trying to build an API and I am concerned that all my resources will either not be accessible with the api.myapp.com domain or that they will "live" with the wrong uris.
I have added the CNAME for my domain name to point to my Heroku app.
(ex: browsing to www.myapp.com takes you to https://myherokuapp.heroku.com)
I would like to set up an API subdomain, so that a GET to
https://api.myapp.com takes you to https://myherokuapp.heroku.com/api/v1
The best scenario would be that a POST to https://api.myapp.com/accounts/12345 would create a new account. Is that even possible?
(I know that subdomains (eg: mysubdomain.myappname.heroku.com) are not possible with Heroku)
I believe the answer could be in three different places:
Something to do with DNS provider forwarding configs (maybe
something to do with "A" records).
Something to config in Heroku, possibly a paid add-on to handle domains/subdomains.
Handle all subdomains within my app.

If you want to differentiate between api.mydomain.com and www.mydomain.com and have different controllers for your API requests then you could certainly use Rails routes constrained to your api subdomain to handle this
constraints :subdomain => "api" do
scope :module => "api", :as => "api" do
resources :posts
end
end
which would then use the posts_controller.rb in the app/controllers/api folder of your application.
You'll then have both www.mydomain.com and api.mydomain.com added a custom domains for your application and then the routes will take care of the rest.
You might also want to look into the Grape Gem for helping build your api

Related

Subdomain routing with devise not working on heroku

I have defined a few types of users using devise (members, company_users, etc) and I'd like to use different subdomains for the login pages of each type of user.
I've referred to this railscast in order to implement the matching of the subdomain and redirect to the appropriate action. My routes.rb file looks like this:
devise_for :company_users, :controllers => { :registrations => 'company_users/registrations', :sessions => 'company_users/sessions' }
devise_scope :company_user do
constraints Subdomain do
match '/' => 'company_users/sessions#new'
end
end
And my lib/subdomain.rb file:
class Subdomain
def self.matches?(request)
request.subdomain.present? and request.subdomain =~ /\Acompanies\z/
end
end
Locally, it works perfectly. I've tested using companies.lvh.me:3000 (as the same railscast suggests) and it really redirects to the correct login page.
In order to try and make it work on Heroku I have added the domain, using heroku domains:add companies.mydomain.com, and I have added a new CNAME record on my DNS server, pointing to my Heroku application.
However, when I try to access companies.mydomain.com it redirects me to the root path, and not to the correct login page. I'm kind of clueless of what's happening. Any help will be appreciated.
This happen when the tld of your domain is different from tld of the heroku domain.
Mine is .com.br and I have to add config.action_dispatch.tld_length = 2 to production.rb, so Rails can parse the URL correctly and redirect to the right subdomain.

Devise Authentication for users from Multiple GApps Domains

I have a rails app with Devise 1.4.9. Currently, it allows only users from mydomain.com to use the application. I need to open it up to some contractors that work for me. Their domain is theirdomain.com.
How do I expand this line from the OmniAuth guide to allow users from two domains?
config.omniauth :google_apps, :store => OpenID::Store::Filesystem.new('/tmp'), :domain => 'mydomain.com'
Include 'theirdomain.com' as well.
And also, how do I write a test for it? I've already written spec tests with sign_in_user "test", but they pass even without "test#mydomain.com". I don't have an account on their domain so cannot test easily.
Thanks!
This doesn't seem like it'll work. I did a deep dive into the gem code and it only supports one domain.
I'm going to switch to open id instead.

rails 3.0 subdomains and formats

I have 2 subdomains that point to one rails application. My rails application's controllers should serve both subdomains.
Lets call the subdomains www.mydomain.com and demo.mydomain.com. I want 2 to accomplish 3 things:
Make sure only some of my controllers serve www.mydomain.com and some serve both domains.
Make sure only a subset of my controllers' actions serve www.mydomain.com and some serve both domains.
Make sure users use only format :html for demo.mydomain.com (e.g. http://demo.mydomain.com/index.html) and use only formats :json/:xml for www.mydomain.com (e.g. http://www.mydomain.com/index.json).
What's the best way to accomplish both requests ?
Perhaps take a look at request routing based on subdomain
How do I route by domain / subdomain in rails
http://agilewebdevelopment.com/plugins/request_routing
where the request_routing plugin would allow you to define routing requirements that test methods/properties of the request object such as subdomain, domain, port. You can test them either against a value or with a Regexp (assuming the method returns a string).
If you're using rails 3 you could also check out subdomaining your rails site
http://railscasts.com/episodes/221-subdomains-in-rails-3
In order to get your controllers to respond differently based on subdomain, you can use a conditional based on
#host = request.host

rails 3 sessions across subdomains not working in Internet Explorer

I am working on a rails 3 application which use subdomains. I used railscasts #221 "Subdomains in rails 3" (http://railscasts.com/episodes/221-subdomains-in-rails-3) as a guide and everything goes well, except in Explorer.
To keep my session across all the subdomains I put the next line in session_store.rb as the tutorial says:
MyApp.application.config.session_store :cookie_store, :key => '_myapp_session', :domain => "example.com"
I have tested my app on Firefox and Chrome and it works well, but for some reason is not working at all in Internet Explorer. The behavior is strange because sometimes it seems the session is share across all my subdomains, but some others there are some subdomains where I am logged in and other sudomains where I am not logged in.
I can't find any reason for this and I would appreciate any idea...
I am using Devise for authentication with rails 3.0.5
I believe you'll need to change your domain value to .example.com (the leading dot indicates that the cookie can be used across subdomains):
MyApp.application.config.session_store :cookie_store, :key => '_myapp_session', :domain => ".example.com"
For some reason this did not work (rails 3.2.11) for any session data that was set on a subdomain. It took a piece of custom Middleware to fix it. A summary of that solution is below.
tl;dr: You need to write a custom Rack Middleware. You need add it into your conifg/environments/[production|development].rb. This is on Rails 3.2.11
Cookie sessions are usually stored only for your top level domain.
If you look in Chrome -> Settings -> Show advanced settings… -> Privacy/Content settings… -> All cookies and site data… -> Search {yourdomain.com} You can see that there will be separate entries for sub1.yourdomain.com and othersub.yourdomain.com and yourdomain.com
The challenge is to use the same session store file across all subdomains.
Step 1: Add Custom Middleware Class
This is where Rack Middleware comes in. Some relevant rack & rails resources:
Railscasts about Rack
Railsguide for Rack
Rack documentation for sesssions abstractly and for cookie sessions
Here is a custom class that you should add in the lib
This was written by #Nader and you all should thank him
# Custom Domain Cookie
#
# Set the cookie domain to the custom domain if it's present
class CustomDomainCookie
def initialize(app, default_domain)
#app = app
#default_domain = default_domain
end
def call(env)
host = env["HTTP_HOST"].split(':').first
env["rack.session.options"][:domain] = custom_domain?(host) ? ".#{host}" : "#{#default_domain}"
#app.call(env)
end
def custom_domain?(host)
host !~ /#{#default_domain.sub(/^\./, '')}/i
end
end
Basically what this does is that it will map all of your cookie session data back onto the exact same cookie file that is equal to your root domain.
Step 2: Add To Rails Config
Now that you have a custom class in lib, make sure are autoloading it. If that meant nothing to you, look here: Rails 3 autoload
The first thing is to make sure that you are system-wide using a cookie store. In config/application.rb we tell Rails to use a cookie store.
# We use a cookie_store for session data
config.session_store :cookie_store,
:key => '_yourappsession',
:domain => :all
The reason this is here is mentioned here is because of the :domain => :all line. There are other people that have suggested to specify :domain => ".yourdomain.com" instead of :domain => :all. For some reason this did not work for me and I needed the custom Middleware class as described above.
Then in your config/environments/production.rb add:
config.middleware.use "CustomDomainCookie", ".yourdomain.com"
Note that the preceding dot is necessary. See "sub-domain cookies, sent in a parent domain request?" for why.
Then in your config/environments/development.rb add:
config.middleware.use "CustomDomainCookie", ".lvh.me"
The lvh.me trick maps onto localhost. It's awesome. See this Railscast about subdomains and this note for more info.
Hopefully that should do it. I honestly am not entirely sure why the process is this convoluted, as I feel cross subdomain sites are common. If anyone has any further insights into the reasons behind each of these steps, please enlighten us in the comments.

Can I mix top-level domain with subdomain applications on Heroku using "Custom Domains" add-on?

According to heroku, http://addons.heroku.com/custom_domains
"The wildcard domain add-on enables you to use *.yourdomain.com. You can have as many wildcard domains as you like on one app."
Let say i have a domain call abc.com
can i use abc.com for 1st rails app, another.abc.com for 2nd rails app, another2.abc.com for 3nd rails app? this 3 rails is separate/different heroku rails app? i would like to know cause heroku say "as many wildcard domains as you like on one app."
Yes, this should be possible. You can condense your apps basically into 1 (if even necessary), and follow the guide here
http://www.railsdev.ws/blog/10/using-subdomains-in-rails-apps/
to learn how to route based on subdomains.
If you have 3 separate applications on Heroku as you describe then you just need a single custom domain per application (ie not the wildcard addon). If you use the wildcard domain addon to add say *.mydomain.com then you will not be able to use the same domain (mydomain.com) for any subsequent applications you host on Heroku.