- 更新日: 2017年2月3日
- Rails
Railsでrequest.urlとrequest.original_urlの違い
Rails で request.url と request.original_url の違いが気になって、ActionDispatch ソースコードを少し読んでみました。結果としては、両者には実装方法に違いがあるのが分かった。
ビューに…
1 |
<%= request.class %> |
と書くなどして確認すると分かりますが、request は ActionDispatch::Request クラスのオブジェクトです。
— 環境 —
Rails 5
request.url
request.url は ActionDispatch::Http::URL モジュール(action_dispatch/http/url.rb)で実装されています。
1 2 3 4 5 6 7 |
module ActionDispatch module Http module URL def url protocol + host_with_port + fullpath end |
rails/url.rb at master – rails/rails
この ActionDispatch::Http::URL モジュールは、ActionDispatch::Request クラスで include されています。
request.original_url
request.original_url は、ActionDispatch::Request クラス(action_dispatch/http/request.rb)で実装されています。
1 2 3 4 5 6 7 8 9 10 11 |
require "rack/request" require "action_dispatch/http/url" module ActionDispatch class Request include Rack::Request::Helpers include ActionDispatch::Http::URL def original_url base_url + original_fullpath end |
rails/request.rb at master – rails/rails
ActionDispatch::Http::URL モジュールをインクルードしてあるので、request.url のように ActionDispatch::Request#url インスタンスメソッドを使える。
original_url の実装で使われている base_url は Rack に実装されているメソッドです。ActionDispatch::Request が Rack::Request::Helpers をインクルードすることで、ActionDispatch::Request#base_url とインスタンスメソッドとして使えるようになっています。
request.base_url
request.base_url は、Rack::Request::Helpers モジュールに実装されている。
1 2 3 4 5 6 7 8 9 |
module Rack class Request module Helpers def base_url url = "#{scheme}://#{host}" url << ":#{port}" if port != DEFAULT_PORTS[scheme] url end |
rack/request.rb at master – rack/rack
ということで以上、request.url と request.original_url は実装に違いにあることが分かりました。
もう少し request.url と request.original_url の違いを読み解く
request.original_url のほうは Rack 層の base_url を使って実装されています。そのため request.url と request.original_url では通信プロトコルの実装部分、各々 protocol と scheme を使っている箇所等が異なることになる。
ソースコードを追うと分かりますが、通信プロトコル部分を返す実装に以下のような違いがあります。
ActionDispatch::Http::URL
1 2 3 |
def protocol @protocol ||= ssl? ? "https://" : "http://" end |
rails/url.rb at master · rails/rails
Rack::Request::Helpers
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def scheme if get_header(HTTPS) == 'on' 'https' elsif get_header(HTTP_X_FORWARDED_SSL) == 'on' 'https' elsif get_header(HTTP_X_FORWARDED_SCHEME) get_header(HTTP_X_FORWARDED_SCHEME) elsif get_header(HTTP_X_FORWARDED_PROTO) get_header(HTTP_X_FORWARDED_PROTO).split(',')[0] else get_header(RACK_URL_SCHEME) end end |
rack/request.rb at master · rack/rack
なので、http または https のみを利用する場合は request.url を使う、という理解で良いのかな? request.original_url(通信プロトコル取得が scheme メソッドによる実装)の場合、プロトコルが http/https じゃない場合でも環境変数 RACK_URL_SCHEME に値を設定すれば、任意の通信プロトコルを返せる実装になっている…(このへんあまり自信ありません)
とりあえずここまでです。request.fullpath と request.original_fullpath の違い等も、同様の手順でソースコードを追うことができます。
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
- window.NREUMがHTMLヘッダー部に自動挿入されるのはNew Relic用
Leave Your Message!