PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/ramaze/current/request.rb

https://github.com/areijonen/ramaze
Ruby | 222 lines | 110 code | 38 blank | 74 comment | 11 complexity | e0bb2aef13027a0cef1ad5c607b2647a MD5 | raw file
Possible License(s): GPL-2.0
  1. # Copyright (c) 2008 Michael Fellinger m.fellinger@gmail.com
  2. # All files in this distribution are subject to the terms of the Ruby license.
  3. require 'rack/request'
  4. module Ramaze
  5. # The purpose of this class is to act as a simple wrapper for Rack::Request
  6. # and provide some convinient methods for our own use.
  7. class Request < ::Rack::Request
  8. class << self
  9. # get the current request out of STATE[:request]
  10. #
  11. # You can call this from everywhere with Ramaze::Request.current
  12. def current() Current.request end
  13. end
  14. # you can access the original @request via this method_missing,
  15. # first it tries to match your method with any of the HTTP parameters
  16. # then, in case that fails, it will relay to @request
  17. def method_missing meth, *args
  18. key = meth.to_s.upcase
  19. return env[key] if env.has_key?(key)
  20. super
  21. end
  22. # the full request URI provided by Rack::Request e.g. http://localhost:7000/controller/action?foo=bar.xhtml
  23. def request_uri
  24. env['REQUEST_URI'] || path_info
  25. end
  26. # the IP address(s) making the request provided by Rack::Request. You shouldn't trust it
  27. def ip
  28. if addr = env['HTTP_X_FORWARDED_FOR']
  29. addr.split(',').last.strip
  30. else
  31. env['REMOTE_ADDR']
  32. end
  33. end
  34. # Request is from a local network?
  35. # Checks both IPv4 and IPv6
  36. ipv4 = %w[ 127.0.0.1/32 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 ]
  37. ipv6 = %w[ fc00::/7 fe80::/10 fec0::/10 ::1 ]
  38. LOCAL = (ipv4 + ipv6).map{|a| IPAddr.new(a)} unless defined?(LOCAL)
  39. # returns true if the IP address making the request is from local network.
  40. # Optional argument address can be used to check any IP address.
  41. def local_net?(address = ip)
  42. addr = IPAddr.new(address)
  43. LOCAL.find{|range| range.include?(addr) }
  44. rescue ArgumentError => ex
  45. raise ArgumentError, ex unless ex.message == 'invalid address'
  46. end
  47. def [](key, *rest)
  48. return params[key.to_s] if rest.empty?
  49. [key, *rest].map{|k| params[k.to_s] }
  50. end
  51. # Sets any arguments passed as @instance_variables for the current action.
  52. #
  53. # Usage:
  54. # request.params # => {'name' => 'manveru', 'q' => 'google', 'lang' => 'de'}
  55. # to_ivs(:name, :q)
  56. # @q # => 'google'
  57. # @name # => 'manveru'
  58. # @lang # => nil
  59. def to_ivs(*args)
  60. instance = Action.current.instance
  61. args.each do |arg|
  62. next unless value = self[arg]
  63. instance.instance_variable_set("@#{arg}", value)
  64. end
  65. end
  66. # Wrapping Request#params to support a one-level hash notation.
  67. # It doesn't support anything really fancy, so be conservative in its use.
  68. #
  69. # See if following provides something useful for us:
  70. # http://redhanded.hobix.com/2006/01/25.html
  71. #
  72. # Example Usage:
  73. #
  74. # # Template:
  75. #
  76. # <form action="/paste">
  77. # <input type="text" name="paste[name]" />
  78. # <input type="text" name="paste[syntax]" />
  79. # <input type="submit" />
  80. # </form>
  81. #
  82. # # In your Controller:
  83. #
  84. # def paste
  85. # name, syntax = request['paste'].values_at('name', 'syntax')
  86. # paste = Paste.create_with(:name => name, :syntax => syntax)
  87. # redirect '/'
  88. # end
  89. #
  90. # # Or, easier:
  91. #
  92. # def paste
  93. # paste = Paste.create_with(request['paste'])
  94. # redirect '/'
  95. # end
  96. def params
  97. return {} if put?
  98. return @ramaze_params if @ramaze_params
  99. begin
  100. @rack_params ||= super
  101. rescue EOFError => ex
  102. @rack_params = {}
  103. Log.error(ex)
  104. end
  105. @ramaze_params = {}
  106. @rack_params.each do |key, value|
  107. if key =~ /^(.*?)(\[.*\])/
  108. prim, nested = $~.captures
  109. ref = @ramaze_params
  110. keys = nested.scan(/\[([^\]]+)\]/).flatten
  111. keys.unshift prim
  112. keys.each_with_index do |k, i|
  113. if i + 1 >= keys.size
  114. ref[k] = value
  115. else
  116. # in case the value is a string we cannot let it be ref next
  117. # time, so throw it away
  118. if ref[k].is_a?(String)
  119. ref = ref[k] = {}
  120. else
  121. ref = ref[k] ||= {}
  122. end
  123. end
  124. end
  125. else
  126. @ramaze_params[key] = value
  127. end
  128. end
  129. @ramaze_params
  130. end
  131. # Interesting HTTP variables from env
  132. def http_vars
  133. env.reject{ |k,v|
  134. k.to_s !~ /USER|HOST|REQUEST|REMOTE|FORWARD|REFER|PATH|QUERY|VERSION|KEEP|CACHE/
  135. }
  136. end
  137. # Returns a string presentation of the request, useful for debugging
  138. # parameters of the action.
  139. def to_s
  140. p, c, e = params.inspect, cookies.inspect, http_vars.inspect
  141. %{#<Ramaze::Request params=#{p} cookies=#{c} env=#{e}>}
  142. end
  143. alias inspect to_s
  144. # Pretty prints current action with parameters, cookies and
  145. # enviroment variables.
  146. def pretty_print pp
  147. p, c, e = params, cookies, http_vars
  148. pp.object_group(self){
  149. { 'params' => params,
  150. 'cookies' => cookies,
  151. 'env' => http_vars }.each do |name, hash|
  152. pp.breakable
  153. pp.text " @#{name}="
  154. pp.nest(name.length+3){ pp.pp_hash hash }
  155. end
  156. }
  157. end
  158. # Answers with a subset of request.params with only the key/value pairs for
  159. # which you pass the keys.
  160. # Valid keys are objects that respond to :to_s
  161. #
  162. # Example:
  163. # request.params
  164. # # => {'name' => 'jason', 'age' => '45', 'job' => 'lumberjack'}
  165. # request.sub('name')
  166. # # => {'name' => 'jason'}
  167. # request.sub(:name, :job)
  168. # # => {'name' => 'jason', 'job' => 'lumberjack'}
  169. def subset(*keys)
  170. keys = keys.map{|k| k.to_s }
  171. params.reject{|k,v| not keys.include?(k) }
  172. end
  173. def domain(path = '/')
  174. scheme = env['rack.url_scheme'] || 'http'
  175. host = env['HTTP_HOST']
  176. URI("#{scheme}://#{host}#{path}")
  177. end
  178. # Returns and array of locales from env['HTTP_ACCEPT_LANGUAGE].
  179. # e.g. ["fi", "en", "ja", "fr", "de", "es", "it", "nl", "sv"]
  180. def locales
  181. env['HTTP_ACCEPT_LANGUAGE'].to_s.split(/(?:,|;q=[\d.,]+)/)
  182. end
  183. end
  184. end