Let’s say you have a blog application, which is built on Ruby on Rails. In the application, each registered user will have his personal blog page at the URL: yourblogapp.com/blogs/blogid
Perhaps, the user has his own website, say, someone.com. It will be nicer to let the user have a custom domain in your blog application (in this example: blog.someone.com).
After some digging, I found the implementation in Rails is quite simple and straightforward.
Requirements
- Your application must running on a dedicated IP. Or at least, if running on a virtual hosting without a dedicated IP, it must be set to the default vhost site, in order to allow all requests from foreign domains be routed to your application.
- In your blog table add a field to record custom domain set by the user. Something like:
add_column(:blogs, :custom_domain, :string, :limit=>200)
And provide an web interface to let the user custom it.
Implementation in Rails
Rails has a built-in URL rewriting module, which redirects incoming requests to controllers and actions. This router makes things a lot easier. But the packaged Routing module only understand request from native domain, and so all we need to do is to extend it to parse requests from foreign domain.
The Routing module provides two extendible methods to define the condition for request parsing. Dan Webb’s Request Routing plugin (alternative link) has already taken care of them and give extra conditions for defining map rules.
So, install the plugin:
ruby script/plugin install http://svn.danwebb.net/external/rails/plugins/request_routing/trunk/
Then create a new map rule in routes.rb
# route all requrest from foriegn domain to boards controller
map.connect(
‘:action/:id’,
:controller => ‘blogs’,
:conditions => {
:domain => /\A(?!(yourblogapp\.com))/i
}
)
This map rule says all requests which are not coming from “yourblogapp.com” will be redirect to the blogs controller.
Then in blogs_controller, you will probably have something like:
def retrieve_blog
@blog = Blog.find_by_id(params['id'])
…..
end
Change this retrieving method to:
def retrieve_blog
@blog = (request.domain != ‘yourblogapp.com’) ?
Blog.find_by_id params['id'] :
Blog.find_by_custom_domian request.host.downcase
…..
end
Job done.
What the user needs to do
To custom a domain for his blog, the user need to do following two setup:
- Create a CNAME record for this domain: blog.someone.com, the destination of which is the domain of your application: yourblogapp.com
- Log in your application, and add “blog.someone.com” to his preference settings.