http://twitter.com/codinghorror
http://twitter.com/login
These both look like twitter accounts but the second one is not. It's a system page.
How does twitter know that logout is not a username and how does it make sure that no user registers under a system page name that exist or that may come into existance in future?
In most url routing frameworks there is a precedence order for your routing rules. Usually fist come first serve, so that the first url patten that matches controls the url.
In this case lets say twitter had to routes defined
map.connect 'login', :controller => 'auth', :action => 'login'
map.connect ':username', :controller => 'user', :action => 'show'
The first route would match the url twitter.com/login , but when you type in twitter.com/coddinghorror it would fail to match the first route and then match the second.
They cannot know in advance. What development they will be doing years ahead. But of curse the could reserve words for trends, current and coming projects - just in case.
The login/logout part is easily achieved by rewriting/routing the url
/login/ - go to login code
/([a-z]+?)/ - go to user page appending $1
Good question?
My guess is that twitter has special logic that checks the username (check for special words) and utilizes URL rewriting and routing accordingly.
I'd be curious to see a snippet of the code though :)
Related
A seemlingly simple problem which I can't figure out how to deal with (in Rails 3.2): we would like to offer the possibility to
our users to define a subdomain and map incoming requests using that subdomain to a path partially retrieved from
the database. So for example, while www.example.com will go to our usual root path, a request to steve.example.com
would first look up "steve" in a datbase table that associates subdomains with ids, and if a match is found route
the request to, say, www.example.com/folders/36 (where 36 is the id associated with "steve"), and if no match is found
continue looking for other routes in routes.rb.
I have a working solution using redirect, which goes something like:
constraints :subdomain => /^(?!www).+/ do # a subdomain is used and different from www
match '*path', :to => redirect {|params, req|
req_protocol=req.env['rack.url_scheme'] # e.g. "http"
req_host=req.env['HTTP_HOST'] # e.g. "steve.example.local:3000"
...
code to pick up "steve", do the lookup and return a suitable URL
}
end
Now, I do NOT want to use redirects for two reasons: firstly the URL is then modified in the user's browser address bar,
and secondly browsers tend to cache the redirects (even with status set to 302 or 307) making such a solution less dynamic.
If I had had access to the request object in routes.rb, I could possibly had done something like
match '*path' => "folders##{index}", :constraints => {:subdomain => /^(?!www).+/ }
after having retrieved index from the database table using the subdomain, but the request object is not available.
(I could however probably manage the case when no association is found using the "Advanced Contstraints" as described in the
Rails guide, although I haven't tested that, knowing that it would only fix a tiny part of the problem).
I want to create referral links like.
www.abc.com/1234
www.abc.com/4345
Where number are the referral codes which will be unique for every user. I am sure this can be done in ruby on rails with some routes configuration. Means where the request will be routed. Which controller? which action? How to get value of unique code.
ps: launchrock is using referral links like this.
You can use this structure with route matching but you would need to have the referral codes match a specific pattern. If, for example, they matched the format of 3 letters followed by three numbers, you could put the following your routes file:
match '/:referrer_id' => 'app#index', :constraints => {:referrer_id => /[a-zA-Z]{3}[0-9]{3}/}
The reference to app#index should be changed to the controller in which you handle referrals and you can access the referrer_id through params[:referrer_id].
Certainly have a look at the link referenced in Markus' answer for suggestions on how to generate the tokens.
I have a link in my bookmarks with regard to token generation: http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby
In your application you will need to store the individual tokens in the user table. Controller and action are up to you and for the routes you could go with something like www.abc.com/referral?123456.
routes.rb
match "/referral/:ref" => "controller#action"
access in controller with:
params[:ref]
Coming from Django, I'm used to be able to organize my URL routings any way I see fit. For example, user registration would exist under the /users/ url.
/users/
/users/registration/
/users/registration/optin/
/users/registration/thankyou/
However, I'm creating a user registration system in CakePHP and the default convention behaviour for url routings is /controller/action/. This yields:
/users/
/users/registration/
/users/optin/
/users/thankyou/
How can I achieve a /controller/action/custom/ style-url routing on some of my actions (where /custom/ is a sub-section, not a parameter)? Should I even be expecting to do this or am I just fighting the convention?
/controller/action/custom/ works fine by default.
It invokes ControllerController::action('custom').
If you're looking for something like invoking UsersController::thankyou() through the URL /users/registration/thankyou, you can make an appropriate route:
Router::connect('/users/registration/thankyou',
array('controller' => 'users', 'action' => 'thankyou'));
You can group routes in one rule like this:
// Routes /users/registration/optin and /users/registration/thankyou to
// UsersController::optin() and UsersController::thankyou() respectively
Router::connect('/users/registration/:action',
array('controller' => 'users'),
array('action' => '(optin|thankyou)'));
Routes are very powerful and completely flexible in Cake. As always, study the manual:
http://book.cakephp.org/view/945/Routes-Configuration
The basics are that the Router matches the route, e.g. '/users/registration/:action', against the current URL, including conditions specified in the third parameter, e.g. 'action' => '(optin|thankyou)' (the :action part has to match the RegEx /^(optin|thankyou)$/).
If it matches, it merges the defaults from the second parameter with any information extracted from the URL, so you get array('controller' => 'users', 'action' => 'thankyou') for example.
It then pushes it through CakeRoute::parse, which constructs the array you can see when doing debug($this->params) in a controller. This array is used to figure out which Controller to load and which action to invoke.
The basic RegEx and parameter matching is already very powerful, but you can go completely crazy by subclassing CakeRoute and providing a custom parse function, as briefly explained at the end of the manual. :)
I'm putting together a short URL functionality for an app I'm working on and now have it working and turning longer URLs into a short URL by base36 encoding the ID of a record pointing to the longer URL, for example:
http://localhost:3000/7ps -> http://localhost:3000/the/long/url
I am struggling to write a route which will intercept requests for the short URL whilst still allowing requests for other valid URLs in the app.
Is there a route I can use which will only target base36 encoded values after the domain?
Thanks for any help!
You can add:
map.encoded ":encoded_url", :controller => :encoded_urls, :action => :please_decode_me
at the end of your routes. Then it shoudl catch everything that is not catched by other routes.
The short answer is "it depends." You can add a route at the end of your routes file as a catch-all. However, if you have any real routes that are one word long, this will eventually fail.
For example: If you have a path that looks like http://localhost:3000/home which is it? Is that the home page or the short URL for object #825062? Any single-word path you have in your app is going to have this issue.
A very easy way around this would be to add a single character as the first directory in your URI.
http://localhost:3000/r/abc123
Or whatever letter you want. Then you can easily map anything that starts with /r/ to your short-URL lookup controller.
map.connect "/r/:short_url", :controller => "controller_name", :action => "name_of_action_that_looks_up_short_urls"
I would like to use create a rails route for a user's open id. The url would look something like
http://mysite.com/identity/:html_encoded_openid
or
http://mysite.com/identity/:html_encoded_openid.xml
This would be so that the site could be queried for an open id and either view info for that identity or receive an xml document containing that information. Standard Rails stuff.
I am looking for your expertise on a few things:
Standard rails routes seem to choke the .s in an openid so that:
http://mysite.com/identity/openid
would find a route but
http://mysite.com/identity/openid.myopenid.com
would not.
What security issues would I need to look out for?
Is there a better way to encode the query, perhaps with the querystring?
And I'd rather not do the standard friendly url method of using:
my-friendly-openid-com
or
23-my-friendly-openid-com
if possible.
You could handle that second route with something like this (replace the action name with something real).
map.connect 'identity/:id', :controller => "identity",
:action => "foo",
:requirements => {:id => /(\w+\.?)+/}