Railsのrequest.urlで使われるHTTPヘッダを調べる

## 概要
railsの`request.url` で使われるHTTPヘッダを調べたので、そのメモ。

## 環境
- Rails 5.0.1
- ruby 2.3.3

## urlクラス
vendor/bundle/ruby/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/http/url.rb

このクラスが `request.url` を作っている。
以下は関連個所のみの抜粋、これだけ調べれば全容は分かりそう。

```rb
      def url
        protocol + host_with_port + fullpath
      end

      def host_with_port
        "#{host}#{port_string}"
      end

      def port_string
        standard_port? ? '' : ":#{port}"
      end

      def protocol
        @protocol ||= ssl? ? 'https://' : 'http://'
      end
```


`url` は、 `protocol + host_with_port + fullpath` なので、この3つを追う。

その他も同じように、メソッド内で呼ばれているものを更に追う。

| メソッド | 呼ばれているもの |
| --- | --- |
| url | protocol, <br>host_with_port, <br>fullpath |
| host_with_port | host, <br>port_string |
| port_string | port |
| protocol | ssl |


## requestクラス
`url` メソッドの `fullpath` を調べようと思いrequestクラスを見たところ、 `super` を呼んでいるので、
このクラスはスルーし親クラスを探ることにする。

vendor/bundle/ruby/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/http/request.rb
関連個所のみ抜粋

```rb
    # Returns the +String+ full path including params of the last URL requested.
    #
    #    # get "/articles"
    #    request.fullpath # => "/articles"
    #
    #    # get "/articles?page=2"
    #    request.fullpath # => "/articles?page=2"
    def fullpath
      @fullpath ||= super
    end
```

## request親クラス
vendor/bundle/ruby/2.3.0/gems/rack-2.0.1/lib/rack/request.rb
関連個所のみ抜粋

```rb
      def script_name;     get_header(SCRIPT_NAME).to_s                   end
      def path_info;       get_header(PATH_INFO).to_s                     end
      def query_string;    get_header(QUERY_STRING).to_s                  end

      def path
        script_name + path_info
      end

      def fullpath
        query_string.empty? ? path : "#{path}?#{query_string}"
      end

      def host
        # Remove port number.
        host_with_port.to_s.sub(/:\d+\z/, '')
      end

      def host_with_port
        if forwarded = get_header(HTTP_X_FORWARDED_HOST)
          forwarded.split(/,\s?/).last
        else
          get_header(HTTP_HOST) || "#{get_header(SERVER_NAME) || get_header(SERVER_ADDR)}:#{get_header(SERVER_PORT)}"
        end
      end

      def port
        if port = host_with_port.split(/:/)[1]
          port.to_i
        elsif port = get_header(HTTP_X_FORWARDED_PORT)
          port.to_i
        elsif has_header?(HTTP_X_FORWARDED_HOST)
          DEFAULT_PORTS[scheme]
        elsif has_header?(HTTP_X_FORWARDED_PROTO)
          DEFAULT_PORTS[get_header(HTTP_X_FORWARDED_PROTO).split(',')[0]]
        else
          get_header(SERVER_PORT).to_i
        end
      end

      def ssl?
        scheme == 'https'
      end
```

| メソッド | 呼ばれているもの |
| --- | --- |
| fullpath | path, <br>query_string |
| path | script_name, <br>path_info |
| host | host_with_port |


と追っていくと、最終的に、下記のHTTPヘッダが使われていることが分かる。

| メソッド | ヘッダ |
| --- | --- |
| script_name | SCRIPT_NAME | 
| path_info | PATH_INFO | 
| query_string | QUERY_STRING | 
| host_with_port | HTTP_HOST, <br>SERVER_NAME, <br>SERVER_ADDR, <br>SERVER_PORT |
| port | HTTP_X_FORWARDED_PORT, <br>HTTP_X_FORWARDED_HOST, <br>HTTP_X_FORWARDED_PROTO, <br>SERVER_PORT |



## 結論
ということで、 `request.url` で使われるHTTPヘッダは以下となる。

- HTTP_HOST
- QUERY_STRING
- PATH_INFO
- SCRIPT_NAME
- HTTP_X_FORWARDED_HOST
- SERVER_NAME
- SERVER_ADDR
- SERVER_PORT
- HTTP_X_FORWARDED_PORT
- HTTP_X_FORWARDED_HOST
- HTTP_X_FORWARDED_PROTO

以上

## 参考
[[Rails3] 現在のURLを取得（request オブジェクト）](http://rails3try.blogspot.jp/2012/01/rails3-urlrequest.html)
[Railsでrequest.urlとrequest.original_urlの違い](http://easyramble.com/rails-request-url-original_url-differences.html)