GET /@:id みたいなURLで他との衝突を避ける
Webアプリのルーティングにおいて、各ユーザの個別ページを特殊なものにしたい場合にどういうURLにすると便利かという話に触れる。例えばr7kamuraというIDのユーザ用のページは、Twitterだと https://twitter.com/r7kamura で、GitHubだと https://github.com/r7kamura というURLになっている。
GET /:id
だと他のパターンと衝突してしまう
もしユーザページに GET /:id
というパターンを採用すると、他のURLのパターンと競合してしまうという問題がある。どんなときに困るかと言うと、例えば https://twitter.com/about でTwitterというサービスについて説明するWebページを提供しようとすると、aboutというIDを持ったユーザ用のページが提供できなくなってしまう。
この問題に対してよく見られる解決方法の一つは、「ユーザページに GET /:id
というパターンを採用する」という方針は変えず、ユーザのIDに使えない文字列の一覧を用意しておくというもの。例えば、aboutやhelpなどURLに使う可能性の高い文字列を予め確保しておくことになる。しかし、将来利用する文字列を全て予測しておくことは難しい。新しいURLを追加するたびに、同名のIDのユーザが居ないか調べて一安心、という状況は避けたい。
GET /@:id
にしてみる
他のURLと衝突しないようにPrefixを付けておけば良いのだけど、しかしPrefixが付いていないURLがかっこ良いと思っているからこそ困っている。なので「極力Prefix感の薄い文字をPrefixとして付けておく」という方針が、まあそこそこ妥協しつつも折り合いが付けられる範囲で良い。
mediumはそうなっていて、r7kamuraというIDのユーザページは https://medium.com/@r7kamura/ という具合になっている。URLに @
が含まれると最初は抵抗感があるけど、まあ大丈夫大丈夫、慣れてくると気持ちいいしみんなやってる。TwitterやGitHubなど、ユーザIDを @r7kamura
のように表記する文化があるサービスであれば、受け入れられやすい可能性が高い。
例えばRailsであれば、以下のように実装できる。GET /@r7kamura
に対するリクエストが、UsersControllerクラスのshowメソッドで処理され、params[:id]
というパラメータで "r7kamura" という文字列を参照できる。
Rails.application.routes.draw do
get "/@:id" => "users#show"
end