aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/request.rb
blob: f16a109cc7a60b3fca6aef3aac6ff3502181d3dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
module ActionController
  # These methods are available in both the production and test Request objects.
  class AbstractRequest
    # Returns both GET and POST parameters in a single hash.
    def parameters
      # puts "#{request_parameters.inspect} | #{query_parameters.inspect} | #{path_parameters.inspect}"
      @parameters ||= request_parameters.merge(query_parameters).merge(path_parameters).with_indifferent_access
    end

    def method
      env['REQUEST_METHOD'].downcase.intern
    end

    def get?
      method == :get
    end

    def post?
      method == :post
    end

    def put?
      method == :put
    end

    def delete?
      method == :delete
    end

    def head?
      method == :head
    end
    
    
    # Determine originating IP address.  REMOTE_ADDR is the standard
    # but will fail if the user is behind a proxy.  HTTP_CLIENT_IP and/or
    # HTTP_X_FORWARDED_FOR are set by proxies so check for these before
    # falling back to REMOTE_ADDR.  HTTP_X_FORWARDED_FOR may be a comma-
    # delimited list in the case of multiple chained proxies; the first is
    # the originating IP.
    def remote_ip
      return env['HTTP_CLIENT_IP'] if env.include? 'HTTP_CLIENT_IP'

      if env.include? 'HTTP_X_FORWARDED_FOR' then
        remote_ips = env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip|
            ip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
        end

        return remote_ips.first.strip unless remote_ips.empty?
      end

      return env['REMOTE_ADDR']
    end

    # Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify
    # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
    def domain(tld_length = 1)
      host.split('.').last(1 + tld_length).join('.')
    end

    # Returns all the subdomains as an array, so ["dev", "www"] would be returned for "dev.www.rubyonrails.org".
    # You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"]
    # in "www.rubyonrails.co.uk".
    def subdomains(tld_length = 1)
      parts = host.split('.')
      parts - parts.last(1 + tld_length)
    end

    # Receive the raw post data. 
    # This is useful for services such as REST, XMLRPC and SOAP 
    # which communicate over HTTP POST but don't use the traditional parameter format. 
    def raw_post
      env['RAW_POST_DATA']
    end
    
    def request_uri
      unless env['REQUEST_URI'].nil?
        (%r{^\w+\://[^/]+(/.*|$)$} =~ env['REQUEST_URI']) ? $1 : env['REQUEST_URI'] # Remove domain, which webrick puts into the request_uri.
      else  # REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME
        script_filename = env["SCRIPT_NAME"].to_s.match(%r{[^/]+$})
        request_uri = env["PATH_INFO"]
        request_uri.sub!(/#{script_filename}\//, '') unless script_filename.nil?
        request_uri += '?' + env["QUERY_STRING"] unless env["QUERY_STRING"].nil? || env["QUERY_STRING"].empty?
        return request_uri
      end
     end

    def protocol
      env["HTTPS"] == "on" ? 'https://' : 'http://'
    end

    def ssl?
      protocol == 'https://'
    end
  
    # returns the interpreted path to requested resource after
    # all the installation directory of this application was taken into account
    def path
      path = request_uri ? request_uri.split('?').first : ''

      # cut off the part of the url which leads to the installation directory of this app
      path[relative_url_root.length..-1]
    end    
    
    # returns the path minus the web server relative 
    # installation directory
    def relative_url_root
      File.dirname(env["SCRIPT_NAME"].to_s).gsub /(^\.$|^\/$)/, ''
    end

    def port
      env['SERVER_PORT'].to_i
    end

    # Returns a string like ":8080" if the port is not 80 or 443 while on https.
    def port_string
      (protocol == 'http://' && port == 80) || (protocol == 'https://' && port == 443) ? '' : ":#{port}"
    end

    def host_with_port
      env['HTTP_HOST'] || host + port_string
    end
  
    def path_parameters=(parameters)
      @path_parameters = parameters
      @parameters = nil
    end

    def path_parameters
      @path_parameters ||= {}
    end
    
    # Returns true if the request's "X-Requested-With" header contains
    # "XMLHttpRequest". (The Prototype Javascript library sends this header with
    # every Ajax request.)
    def xml_http_request?
      env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
    end
    alias xhr? :xml_http_request?
    
    #--
    # Must be implemented in the concrete request
    #++
    def query_parameters
    end

    def request_parameters
    end

    def env
    end

    def host
    end

    def cookies
    end

    def session
    end

    def reset_session
    end    
  end
end