merb-core 0.9.9 → 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,15 +11,16 @@
11
11
  # some cases. Eventually Rubinius and maybe MRI 2.0 gonna
12
12
  # improve this situation but at the moment, all commonly used
13
13
  # strings, regexp and numbers used as constants so no extra
14
- # objects created and VM just operate pointers.
14
+ # objects created and VM just operates pointers.
15
15
  module Merb
16
16
  module Const
17
-
17
+
18
18
  DEFAULT_SEND_FILE_OPTIONS = {
19
19
  :type => 'application/octet-stream'.freeze,
20
20
  :disposition => 'attachment'.freeze
21
21
  }.freeze
22
-
22
+
23
+ RACK_INPUT = 'rack.input'.freeze
23
24
  SET_COOKIE = " %s=%s; path=/; expires=%s".freeze
24
25
  COOKIE_EXPIRATION_FORMAT = "%a, %d-%b-%Y %H:%M:%S GMT".freeze
25
26
  COOKIE_SPLIT = /[;,] */n.freeze
@@ -34,24 +35,48 @@ module Merb
34
35
  JSON_MIME_TYPE_REGEXP = %r{^application/json|^text/x-json}.freeze
35
36
  XML_MIME_TYPE_REGEXP = %r{^application/xml|^text/xml}.freeze
36
37
  FORM_URL_ENCODED_REGEXP = %r{^application/x-www-form-urlencoded}.freeze
38
+ LOCAL_IP_REGEXP = /^unknown$|^(127|10|172\.16|192\.168)\./i.freeze
39
+ XML_HTTP_REQUEST_REGEXP = /XMLHttpRequest/i.freeze
37
40
  UPCASE_CONTENT_TYPE = 'CONTENT_TYPE'.freeze
38
41
  CONTENT_TYPE = "Content-Type".freeze
39
42
  DATE = 'Date'.freeze
43
+ UPCASE_HTTPS = 'HTTPS'.freeze
44
+ HTTPS = 'https'.freeze
45
+ HTTP = 'http'.freeze
40
46
  ETAG = 'ETag'.freeze
41
47
  LAST_MODIFIED = "Last-Modified".freeze
42
- SLASH = "/".freeze
43
48
  GET = "GET".freeze
44
49
  POST = "POST".freeze
45
50
  HEAD = "HEAD".freeze
46
51
  CONTENT_LENGTH = "CONTENT_LENGTH".freeze
52
+ HTTP_CLIENT_IP = "HTTP_CLIENT_IP".freeze
53
+ HTTP_X_REQUESTED_WITH = "HTTP_X_REQUESTED_WITH".freeze
47
54
  HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR".freeze
55
+ HTTP_X_FORWARDED_PROTO = "HTTP_X_FORWARDED_PROTO".freeze
56
+ HTTP_X_FORWARDED_HOST = "HTTP_X_FORWARDED_HOST".freeze
48
57
  HTTP_IF_MODIFIED_SINCE = "HTTP_IF_MODIFIED_SINCE".freeze
49
58
  HTTP_IF_NONE_MATCH = "HTTP_IF_NONE_MATCH".freeze
50
59
  HTTP_CONTENT_TYPE = "HTTP_CONTENT_TYPE".freeze
51
60
  HTTP_CONTENT_LENGTH = "HTTP_CONTENT_LENGTH".freeze
61
+ HTTP_REFERER = "HTTP_REFERER".freeze
62
+ HTTP_USER_AGENT = "HTTP_USER_AGENT".freeze
63
+ HTTP_HOST = "HTTP_HOST".freeze
64
+ HTTP_CONNECTION = "HTTP_CONNECTION".freeze
65
+ HTTP_KEEP_ALIVE = "HTTP_KEEP_ALIVE".freeze
66
+ HTTP_ACCEPT = "HTTP_ACCEPT".freeze
67
+ HTTP_ACCEPT_ENCODING = "HTTP_ACCEPT_ENCODING".freeze
68
+ HTTP_ACCEPT_LANGUAGE = "HTTP_ACCEPT_LANGUAGE".freeze
69
+ HTTP_ACCEPT_CHARSET = "HTTP_ACCEPT_CHARSET".freeze
70
+ HTTP_CACHE_CONTROL = "HTTP_CACHE_CONTROL".freeze
52
71
  UPLOAD_ID = "upload_id".freeze
53
72
  PATH_INFO = "PATH_INFO".freeze
73
+ HTTP_VERSION = "HTTP_VERSION".freeze
74
+ GATEWAY_INTERFACE = "GATEWAY_INTERFACE".freeze
54
75
  SCRIPT_NAME = "SCRIPT_NAME".freeze
76
+ SERVER_NAME = "SERVER_NAME".freeze
77
+ SERVER_SOFTWARE = "SERVER_SOFTWARE".freeze
78
+ SERVER_PROTOCOL = "SERVER_PROTOCOL".freeze
79
+ SERVER_PORT = "SERVER_PORT".freeze
55
80
  REQUEST_URI = "REQUEST_URI".freeze
56
81
  REQUEST_PATH = "REQUEST_PATH".freeze
57
82
  REQUEST_METHOD = "REQUEST_METHOD".freeze
@@ -59,9 +84,14 @@ module Merb
59
84
  BREAK_TAG = "<br/>".freeze
60
85
  EMPTY_STRING = "".freeze
61
86
  NEWLINE = "\n".freeze
87
+ SLASH = "/".freeze
88
+ DOT = ".".freeze
89
+ QUESTION_MARK = "?".freeze
62
90
  DOUBLE_NEWLINE = "\n\n".freeze
63
91
  LOCATION = "Location".freeze
64
92
  TEXT_SLASH_HTML = "text/html".freeze
65
-
93
+
94
+ WIN_PLATFORM_REGEXP = /(:?mswin|mingw)/.freeze
95
+ JAVA_PLATFORM_REGEXP = /java/.freeze
66
96
  end
67
97
  end
@@ -271,9 +271,9 @@ class Merb::AbstractController
271
271
  #
272
272
  # @api plugin
273
273
  def _dispatch(action)
274
- self._before_dispatch_callbacks.each { |cb| cb.call(self) }
275
274
  self.action_name = action
276
-
275
+ self._before_dispatch_callbacks.each { |cb| cb.call(self) }
276
+
277
277
  caught = catch(:halt) do
278
278
  start = Time.now
279
279
  result = _call_filters(_before_filters)
@@ -544,7 +544,7 @@ class Merb::AbstractController
544
544
  # of protocol and host options.
545
545
  #
546
546
  # @api public
547
- def absolute_url(name, *args)
547
+ def absolute_url(*args)
548
548
  # FIXME: arrgh, why request.protocol returns http://?
549
549
  # :// is not part of protocol name
550
550
  options = extract_options_from_args!(args) || {}
@@ -556,7 +556,7 @@ class Merb::AbstractController
556
556
 
557
557
  args << options
558
558
 
559
- protocol + "://" + host + url(name, *args)
559
+ protocol + "://" + host + url(*args)
560
560
  end
561
561
 
562
562
  # Generates a URL for a single or nested resource.
@@ -74,7 +74,7 @@ module Merb
74
74
  # This would halt execution of your action and re-route it over to your
75
75
  # Exceptions controller which might look something like:
76
76
  #
77
- # class Exceptions < Application
77
+ # class Exceptions < Merb::Controller
78
78
 
79
79
  # def not_found
80
80
  # render :layout => :none
@@ -132,7 +132,7 @@ module Merb
132
132
  #
133
133
  # Add the required action to our Exceptions controller
134
134
  #
135
- # class Exceptions < Application
135
+ # class Exceptions < Merb::Controller
136
136
 
137
137
  # def admin_access_required
138
138
  # render
@@ -335,7 +335,7 @@ class Merb::Controller < Merb::AbstractController
335
335
  options[:protocol] ||= request.protocol
336
336
  options[:host] ||= request.host
337
337
  args << options
338
- super(args.first, *args[1..-1])
338
+ super(*args)
339
339
  end
340
340
 
341
341
  # The results of the controller's render, to be returned to Rack.
@@ -13,7 +13,7 @@ module Merb
13
13
  # Queue:: the current queue of dispatch jobs.
14
14
  #
15
15
  # @api private
16
- def work_queue
16
+ def work_queue
17
17
  @@work_queue
18
18
  end
19
19
 
@@ -1,12 +1,12 @@
1
1
  require 'tempfile'
2
2
 
3
3
  module Merb
4
-
4
+
5
5
  class Request
6
6
  # def env def exceptions def route_params
7
7
  attr_accessor :env, :exceptions, :route
8
8
  attr_reader :route_params
9
-
9
+
10
10
  # by setting these to false, auto-parsing is disabled; this way you can
11
11
  # do your own parsing instead
12
12
  cattr_accessor :parse_multipart_params, :parse_json_params,
@@ -14,7 +14,7 @@ module Merb
14
14
  self.parse_multipart_params = true
15
15
  self.parse_json_params = true
16
16
  self.parse_xml_params = true
17
-
17
+
18
18
  # Flash, and some older browsers can't use arbitrary
19
19
  # request methods -- i.e., are limited to GET/POST.
20
20
  # These user-agents can make POST requests in combination
@@ -23,39 +23,39 @@ module Merb
23
23
  # in the params, or an X-HTTP-Method-Override header
24
24
  cattr_accessor :http_method_overrides
25
25
  self.http_method_overrides = []
26
-
26
+
27
27
  # Initialize the request object.
28
- #
28
+ #
29
29
  # ==== Parameters
30
- # http_request<~params:~[], ~body:IO>::
30
+ # http_request<~params:~[], ~body:IO>::
31
31
  # An object like an HTTP Request.
32
- #
32
+ #
33
33
  # @api private
34
34
  def initialize(rack_env)
35
35
  @env = rack_env
36
- @body = rack_env['rack.input']
36
+ @body = rack_env[Merb::Const::RACK_INPUT]
37
37
  @route_params = {}
38
38
  end
39
-
39
+
40
40
  # Returns the controller object for initialization and dispatching the
41
41
  # request.
42
- #
42
+ #
43
43
  # ==== Returns
44
44
  # Class:: The controller class matching the routed request,
45
45
  # e.g. Posts.
46
- #
46
+ #
47
47
  # @api private
48
48
  def controller
49
49
  unless params[:controller]
50
- raise ControllerExceptions::NotFound,
50
+ raise ControllerExceptions::NotFound,
51
51
  "Route matched, but route did not specify a controller.\n" +
52
52
  "Did you forgot to add :controller => \"people\" or :controller " +
53
- "segment to route definition?\nHere is what's specified:\n" +
53
+ "segment to route definition?\nHere is what's specified:\n" +
54
54
  route.inspect
55
55
  end
56
- path = [params[:namespace], params[:controller]].compact.join("/")
56
+ path = [params[:namespace], params[:controller]].compact.join(Merb::Const::SLASH)
57
57
  controller = path.snake_case.to_const_string
58
-
58
+
59
59
  begin
60
60
  Object.full_const_get(controller)
61
61
  rescue NameError => e
@@ -64,7 +64,7 @@ module Merb
64
64
  raise ControllerExceptions::NotFound, msg
65
65
  end
66
66
  end
67
-
67
+
68
68
  METHODS = %w{get post put delete head options}
69
69
 
70
70
  # ==== Returns
@@ -75,11 +75,11 @@ module Merb
75
75
  # http_method_overrides will be checked for the masquerading method.
76
76
  # The block will get the controller yielded to it. The first matching workaround wins.
77
77
  # To disable this behavior, set http_method_overrides = []
78
- #
78
+ #
79
79
  # @api public
80
80
  def method
81
81
  @method ||= begin
82
- request_method = @env['REQUEST_METHOD'].downcase.to_sym
82
+ request_method = @env[Merb::Const::REQUEST_METHOD].downcase.to_sym
83
83
  case request_method
84
84
  when :get, :head, :put, :delete, :options
85
85
  request_method
@@ -91,33 +91,33 @@ module Merb
91
91
  m.downcase! if m
92
92
  METHODS.include?(m) ? m.to_sym : :post
93
93
  else
94
- raise "Unknown REQUEST_METHOD: #{@env['REQUEST_METHOD']}"
94
+ raise "Unknown REQUEST_METHOD: #{@env[Merb::Const::REQUEST_METHOD]}"
95
95
  end
96
96
  end
97
97
  end
98
-
98
+
99
99
  # create predicate methods for querying the REQUEST_METHOD
100
100
  # get? post? head? put? etc
101
101
  METHODS.each do |m|
102
102
  class_eval "def #{m}?() method == :#{m} end"
103
103
  end
104
-
104
+
105
105
  # ==== Notes
106
106
  # Find route using requested URI and merges route
107
107
  # parameters (:action, :controller and named segments)
108
108
  # into request params hash.
109
- #
109
+ #
110
110
  # @api private
111
111
  def find_route!
112
112
  @route, @route_params = Merb::Router.route_for(self)
113
113
  params.merge! @route_params if @route_params.is_a?(Hash)
114
114
  end
115
-
115
+
116
116
  # ==== Notes
117
117
  # Processes the return value of a deferred router block
118
118
  # and returns the current route params for the current
119
119
  # request evaluation
120
- #
120
+ #
121
121
  # @api private
122
122
  def _process_block_return(retval)
123
123
  # If the return value is an array, then it is a redirect
@@ -127,67 +127,67 @@ module Merb
127
127
  matched! if retval.is_a?(Array)
128
128
  retval
129
129
  end
130
-
130
+
131
131
  # Sets the request as matched. This will abort evaluating any
132
132
  # further deferred procs.
133
- #
133
+ #
134
134
  # @api private
135
135
  def matched!
136
136
  @matched = true
137
137
  end
138
-
138
+
139
139
  # Checks whether or not the request has been matched to a route.
140
- #
140
+ #
141
141
  # @api private
142
142
  def matched?
143
143
  @matched
144
144
  end
145
-
145
+
146
146
  # ==== Returns
147
147
  # (Array, Hash):: the route params for the matched route.
148
- #
148
+ #
149
149
  # ==== Notes
150
150
  # If the response is an Array then it is considered a direct Rack response
151
151
  # to be sent back as a response. Otherwise, the route_params is a Hash with
152
152
  # routing data (controller, action, et al).
153
- #
153
+ #
154
154
  # @api private
155
155
  def rack_response
156
156
  @route_params
157
157
  end
158
-
158
+
159
159
  # If @route_params is an Array, then it will be the rack response.
160
160
  # In this case, the request is considered handled.
161
- #
161
+ #
162
162
  # ==== Returns
163
163
  # Boolean:: true if @route_params is an Array, false otherwise.
164
- #
164
+ #
165
165
  # @api private
166
166
  def handled?
167
167
  @route_params.is_a?(Array)
168
168
  end
169
-
169
+
170
170
  # == Params
171
- #
171
+ #
172
172
  # Handles processing params from raw data and merging them together to get
173
173
  # the final request params.
174
-
174
+
175
175
  private
176
-
176
+
177
177
  # ==== Returns
178
178
  # Hash:: Parameters passed from the URL like ?blah=hello.
179
- #
179
+ #
180
180
  # @api private
181
181
  def query_params
182
182
  @query_params ||= self.class.query_parse(query_string || '')
183
183
  end
184
-
184
+
185
185
  # Parameters passed in the body of the request. Ajax calls from
186
186
  # prototype.js and other libraries pass content this way.
187
187
  #
188
188
  # ==== Returns
189
189
  # Hash:: The parameters passed in the body.
190
- #
190
+ #
191
191
  # @api private
192
192
  def body_params
193
193
  @body_params ||= begin
@@ -196,12 +196,12 @@ module Merb
196
196
  end
197
197
  end
198
198
  end
199
-
199
+
200
200
  # ==== Returns
201
201
  # Mash::
202
202
  # The parameters gathered from the query string and the request body,
203
203
  # with parameters in the body taking precedence.
204
- #
204
+ #
205
205
  # @api private
206
206
  def body_and_query_params
207
207
  # ^-- FIXME a better name for this method
@@ -211,17 +211,17 @@ module Merb
211
211
  h.to_mash
212
212
  end
213
213
  end
214
-
214
+
215
215
  # ==== Raises
216
216
  # ControllerExceptions::MultiPartParseError::
217
217
  # Unable to parse the multipart form data.
218
218
  #
219
219
  # ==== Returns
220
220
  # Hash:: The parsed multipart parameters.
221
- #
221
+ #
222
222
  # @api private
223
223
  def multipart_params
224
- @multipart_params ||=
224
+ @multipart_params ||=
225
225
  begin
226
226
  # if the content-type is multipart
227
227
  # parse the multipart. Otherwise return {}
@@ -229,13 +229,13 @@ module Merb
229
229
  self.class.parse_multipart(@body, $1, content_length)
230
230
  else
231
231
  {}
232
- end
232
+ end
233
233
  rescue ControllerExceptions::MultiPartParseError => e
234
234
  @multipart_params = {}
235
235
  raise e
236
236
  end
237
237
  end
238
-
238
+
239
239
  # ==== Returns
240
240
  # Hash:: Parameters from body if this is a JSON request.
241
241
  #
@@ -244,20 +244,25 @@ module Merb
244
244
  # parameters hash. If it parses to anything else (such as an Array, or
245
245
  # if it inflates to an Object) it will be accessible via the inflated_object
246
246
  # parameter.
247
- #
247
+ #
248
248
  # @api private
249
249
  def json_params
250
250
  @json_params ||= begin
251
251
  if Merb::Const::JSON_MIME_TYPE_REGEXP.match(content_type)
252
- jobj = JSON.parse(raw_post) rescue Mash.new
253
- jobj.kind_of?(Hash) ? jobj : { :inflated_object => jobj }
252
+ begin
253
+ jobj = JSON.parse(raw_post)
254
+ jobj = jobj.to_mash if jobj.is_a?(Hash)
255
+ rescue JSON::ParserError
256
+ jobj = Mash.new
257
+ end
258
+ jobj.is_a?(Hash) ? jobj : { :inflated_object => jobj }
254
259
  end
255
260
  end
256
261
  end
257
-
262
+
258
263
  # ==== Returns
259
264
  # Hash:: Parameters from body if this is an XML request.
260
- #
265
+ #
261
266
  # @api private
262
267
  def xml_params
263
268
  @xml_params ||= begin
@@ -266,30 +271,30 @@ module Merb
266
271
  end
267
272
  end
268
273
  end
269
-
274
+
270
275
  public
271
-
276
+
272
277
  # ==== Returns
273
278
  # Mash:: All request parameters.
274
279
  #
275
280
  # ==== Notes
276
281
  # The order of precedence for the params is XML, JSON, multipart, body and
277
282
  # request string.
278
- #
283
+ #
279
284
  # @api public
280
285
  def params
281
286
  @params ||= begin
282
- h = body_and_query_params.merge(route_params)
287
+ h = body_and_query_params.merge(route_params)
283
288
  h.merge!(multipart_params) if self.class.parse_multipart_params && multipart_params
284
289
  h.merge!(json_params) if self.class.parse_json_params && json_params
285
290
  h.merge!(xml_params) if self.class.parse_xml_params && xml_params
286
291
  h
287
292
  end
288
293
  end
289
-
294
+
290
295
  # ==== Returns
291
296
  # String:: Returns the redirect message Base64 unencoded.
292
- #
297
+ #
293
298
  # @api public
294
299
  def message
295
300
  return {} unless params[:_message]
@@ -299,258 +304,260 @@ module Merb
299
304
  {}
300
305
  end
301
306
  end
302
-
307
+
303
308
  # ==== Notes
304
309
  # Resets the params to a nil value.
305
- #
310
+ #
306
311
  # @api private
307
312
  def reset_params!
308
313
  @params = nil
309
314
  end
310
-
315
+
311
316
  # ==== Returns
312
317
  # String:: The raw post.
313
- #
318
+ #
314
319
  # @api private
315
320
  def raw_post
316
321
  @body.rewind if @body.respond_to?(:rewind)
317
322
  @raw_post ||= @body.read
318
323
  end
319
-
324
+
320
325
  # ==== Returns
321
326
  # Boolean:: If the request is an XML HTTP request.
322
- #
327
+ #
323
328
  # @api public
324
329
  def xml_http_request?
325
- not /XMLHttpRequest/i.match(@env['HTTP_X_REQUESTED_WITH']).nil?
330
+ not Merb::Const::XML_HTTP_REQUEST_REGEXP.match(@env[Merb::Const::HTTP_X_REQUESTED_WITH]).nil?
326
331
  end
327
332
  alias xhr? :xml_http_request?
328
333
  alias ajax? :xml_http_request?
329
-
334
+
330
335
  # ==== Returns
331
336
  # String:: The remote IP address.
332
- #
337
+ #
333
338
  # @api public
334
339
  def remote_ip
335
- return @env['HTTP_CLIENT_IP'] if @env.include?('HTTP_CLIENT_IP')
336
-
340
+ return @env[Merb::Const::HTTP_CLIENT_IP] if @env.include?(Merb::Const::HTTP_CLIENT_IP)
341
+
337
342
  if @env.include?(Merb::Const::HTTP_X_FORWARDED_FOR) then
338
343
  remote_ips = @env[Merb::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip|
339
- ip =~ /^unknown$|^(127|10|172\.16|192\.168)\./i
344
+ ip =~ Merb::Const::LOCAL_IP_REGEXP
340
345
  end
341
-
346
+
342
347
  return remote_ips.first.strip unless remote_ips.empty?
343
348
  end
344
-
349
+
345
350
  return @env[Merb::Const::REMOTE_ADDR]
346
351
  end
347
-
352
+
348
353
  # ==== Returns
349
354
  # String::
350
355
  # The protocol, i.e. either "https" or "http" depending on the
351
356
  # HTTPS header.
352
- #
357
+ #
353
358
  # @api public
354
359
  def protocol
355
- ssl? ? 'https' : 'http'
360
+ ssl? ? Merb::Const::HTTPS : Merb::Const::HTTP
356
361
  end
357
-
362
+
358
363
  # ==== Returns
359
364
  # Boolean::: True if the request is an SSL request.
360
- #
365
+ #
361
366
  # @api public
362
367
  def ssl?
363
- @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
368
+ @env[Merb::Const::UPCASE_HTTPS] == 'on' || @env[Merb::Const::HTTP_X_FORWARDED_PROTO] == Merb::Const::HTTPS
364
369
  end
365
-
370
+
366
371
  # ==== Returns
367
372
  # String:: The HTTP referer.
368
- #
373
+ #
369
374
  # @api public
370
375
  def referer
371
- @env['HTTP_REFERER']
376
+ @env[Merb::Const::HTTP_REFERER]
372
377
  end
373
-
378
+
374
379
  # ==== Returns
375
380
  # String:: The full URI, including protocol and host
376
- #
381
+ #
377
382
  # @api public
378
383
  def full_uri
379
384
  protocol + "://" + host + uri
380
385
  end
381
-
386
+
382
387
  # ==== Returns
383
388
  # String:: The request URI.
384
- #
389
+ #
385
390
  # @api public
386
391
  def uri
387
- @env['REQUEST_PATH'] || @env['REQUEST_URI'] || path_info
392
+ @env[Merb::Const::REQUEST_PATH] || @env[Merb::Const::REQUEST_URI] || path_info
388
393
  end
389
-
394
+
390
395
  # ==== Returns
391
396
  # String:: The HTTP user agent.
392
- #
397
+ #
393
398
  # @api public
394
399
  def user_agent
395
- @env['HTTP_USER_AGENT']
400
+ @env[Merb::Const::HTTP_USER_AGENT]
396
401
  end
397
-
402
+
398
403
  # ==== Returns
399
404
  # String:: The server name.
400
- #
405
+ #
401
406
  # @api public
402
407
  def server_name
403
- @env['SERVER_NAME']
408
+ @env[Merb::Const::SERVER_NAME]
404
409
  end
405
-
410
+
406
411
  # ==== Returns
407
412
  # String:: The accepted encodings.
408
- #
413
+ #
409
414
  # @api private
410
415
  def accept_encoding
411
- @env['HTTP_ACCEPT_ENCODING']
416
+ @env[Merb::Const::HTTP_ACCEPT_ENCODING]
412
417
  end
413
-
418
+
414
419
  # ==== Returns
415
420
  # String:: The script name.
416
- #
421
+ #
417
422
  # @api public
418
423
  def script_name
419
- @env['SCRIPT_NAME']
424
+ @env[Merb::Const::SCRIPT_NAME]
420
425
  end
421
-
426
+
422
427
  # ==== Returns
423
428
  # String:: HTTP cache control.
424
- #
429
+ #
425
430
  # @api public
426
431
  def cache_control
427
- @env['HTTP_CACHE_CONTROL']
432
+ @env[Merb::Const::HTTP_CACHE_CONTROL]
428
433
  end
429
-
434
+
430
435
  # ==== Returns
431
436
  # String:: The accepted language.
432
- #
437
+ #
433
438
  # @api public
434
439
  def accept_language
435
- @env['HTTP_ACCEPT_LANGUAGE']
440
+ @env[Merb::Const::HTTP_ACCEPT_LANGUAGE]
436
441
  end
437
-
442
+
438
443
  # ==== Returns
439
444
  # String:: The server software.
440
- #
445
+ #
441
446
  # @api public
442
447
  def server_software
443
- @env['SERVER_SOFTWARE']
448
+ @env[Merb::Const::SERVER_SOFTWARE]
444
449
  end
445
-
450
+
446
451
  # ==== Returns
447
452
  # String:: Value of HTTP_KEEP_ALIVE.
448
- #
453
+ #
449
454
  # @api public
450
455
  def keep_alive
451
- @env['HTTP_KEEP_ALIVE']
456
+ @env[Merb::Const::HTTP_KEEP_ALIVE]
452
457
  end
453
-
458
+
454
459
  # ==== Returns
455
460
  # String:: The accepted character sets.
456
- #
461
+ #
457
462
  # @api public
458
463
  def accept_charset
459
- @env['HTTP_ACCEPT_CHARSET']
464
+ @env[Merb::Const::HTTP_ACCEPT_CHARSET]
460
465
  end
461
-
466
+
462
467
  # ==== Returns
463
468
  # String:: The HTTP version
464
- #
469
+ #
465
470
  # @api private
466
471
  def version
467
- @env['HTTP_VERSION']
472
+ @env[Merb::Const::HTTP_VERSION]
468
473
  end
469
-
474
+
470
475
  # ==== Returns
471
476
  # String:: The gateway.
472
- #
477
+ #
473
478
  # @api public
474
479
  def gateway
475
- @env['GATEWAY_INTERFACE']
480
+ @env[Merb::Const::GATEWAY_INTERFACE]
476
481
  end
477
-
482
+
478
483
  # ==== Returns
479
484
  # String:: The accepted response types. Defaults to "*/*".
480
- #
485
+ #
481
486
  # @api private
482
487
  def accept
483
- @env['HTTP_ACCEPT'].blank? ? "*/*" : @env['HTTP_ACCEPT']
488
+ @env[Merb::Const::HTTP_ACCEPT].blank? ? "*/*" : @env[Merb::Const::HTTP_ACCEPT]
484
489
  end
485
-
490
+
486
491
  # ==== Returns
487
492
  # String:: The HTTP connection.
488
- #
493
+ #
489
494
  # @api private
490
495
  def connection
491
- @env['HTTP_CONNECTION']
496
+ @env[Merb::Const::HTTP_CONNECTION]
492
497
  end
493
-
498
+
494
499
  # ==== Returns
495
500
  # String:: The query string.
496
- #
501
+ #
497
502
  # @api private
498
503
  def query_string
499
- @env['QUERY_STRING']
504
+ @env[Merb::Const::QUERY_STRING]
500
505
  end
501
-
506
+
502
507
  # ==== Returns
503
508
  # String:: The request content type.
504
- #
509
+ #
505
510
  # @api private
506
511
  def content_type
507
- @env['CONTENT_TYPE']
512
+ @env[Merb::Const::UPCASE_CONTENT_TYPE]
508
513
  end
509
-
514
+
510
515
  # ==== Returns
511
516
  # Fixnum:: The request content length.
512
- #
517
+ #
513
518
  # @api public
514
519
  def content_length
515
520
  @content_length ||= @env[Merb::Const::CONTENT_LENGTH].to_i
516
521
  end
517
-
522
+
518
523
  # ==== Returns
519
524
  # String::
520
525
  # The URI without the query string. Strips trailing "/" and reduces
521
526
  # duplicate "/" to a single "/".
522
- #
527
+ #
523
528
  # @api public
524
529
  def path
525
- path = (uri.empty? ? '/' : uri.split('?').first).squeeze("/")
530
+ # Merb::Const::SLASH is /
531
+ # Merb::Const::QUESTION_MARK is ?
532
+ path = (uri.empty? ? Merb::Const::SLASH : uri.split(Merb::Const::QUESTION_MARK).first).squeeze(Merb::Const::SLASH)
526
533
  path = path[0..-2] if (path[-1] == ?/) && path.size > 1
527
534
  path
528
535
  end
529
-
536
+
530
537
  # ==== Returns
531
538
  # String:: The path info.
532
- #
539
+ #
533
540
  # @api public
534
541
  def path_info
535
- @path_info ||= self.class.unescape(@env['PATH_INFO'])
542
+ @path_info ||= self.class.unescape(@env[Merb::Const::PATH_INFO])
536
543
  end
537
-
544
+
538
545
  # ==== Returns
539
546
  # Fixnum:: The server port.
540
- #
547
+ #
541
548
  # @api public
542
549
  def port
543
- @env['SERVER_PORT'].to_i
550
+ @env[Merb::Const::SERVER_PORT].to_i
544
551
  end
545
-
552
+
546
553
  # ==== Returns
547
554
  # String:: The full hostname including the port.
548
- #
555
+ #
549
556
  # @api public
550
557
  def host
551
- @env['HTTP_X_FORWARDED_HOST'] || @env['HTTP_HOST']
558
+ @env[Merb::Const::HTTP_X_FORWARDED_HOST] || @env[Merb::Const::HTTP_HOST]
552
559
  end
553
-
560
+
554
561
  # ==== Parameters
555
562
  # tld_length<Fixnum>::
556
563
  # Number of domains levels to inlclude in the top level domain. Defaults
@@ -558,13 +565,13 @@ module Merb
558
565
  #
559
566
  # ==== Returns
560
567
  # Array:: All the subdomain parts of the host.
561
- #
568
+ #
562
569
  # @api public
563
570
  def subdomains(tld_length = 1)
564
- parts = host.split('.')
571
+ parts = host.split(Merb::Const::DOT)
565
572
  parts[0..-(tld_length+2)]
566
573
  end
567
-
574
+
568
575
  # ==== Parameters
569
576
  # tld_length<Fixnum>::
570
577
  # Number of domains levels to inlclude in the top level domain. Defaults
@@ -572,32 +579,32 @@ module Merb
572
579
  #
573
580
  # ==== Returns
574
581
  # String:: The full domain name without the port number.
575
- #
582
+ #
576
583
  # @api public
577
584
  def domain(tld_length = 1)
578
- host.split('.').last(1 + tld_length).join('.').sub(/:\d+$/,'')
585
+ host.split(Merb::Const::DOT).last(1 + tld_length).join(Merb::Const::DOT).sub(/:\d+$/,'')
579
586
  end
580
-
587
+
581
588
  # ==== Returns
582
589
  # Value of If-None-Match request header.
583
- #
590
+ #
584
591
  # @api private
585
592
  def if_none_match
586
593
  @env[Merb::Const::HTTP_IF_NONE_MATCH]
587
594
  end
588
-
595
+
589
596
  # ==== Returns
590
597
  # Value of If-Modified-Since request header.
591
- #
598
+ #
592
599
  # @api private
593
600
  def if_modified_since
594
601
  if time = @env[Merb::Const::HTTP_IF_MODIFIED_SINCE]
595
602
  Time.rfc2822(time)
596
603
  end
597
604
  end
598
-
605
+
599
606
  class << self
600
-
607
+
601
608
  # ==== Parameters
602
609
  # value<Array, Hash, Dictionary ~to_s>:: The value for the query string.
603
610
  # prefix<~to_s>:: The prefix to add to the query string keys.
@@ -617,7 +624,7 @@ module Merb
617
624
  # # => "search[page]=10&search[word]=ruby"
618
625
  # params_to_query_string([ "ice-cream", "cake" ], "shopping_list")
619
626
  # # => "shopping_list[]=ice-cream&shopping_list[]=cake"
620
- #
627
+ #
621
628
  # @api private
622
629
  def params_to_query_string(value, prefix = nil)
623
630
  case value
@@ -633,33 +640,33 @@ module Merb
633
640
  "#{prefix}=#{Merb::Request.escape(value)}"
634
641
  end
635
642
  end
636
-
643
+
637
644
  # ==== Parameters
638
645
  # s<String>:: String to URL escape.
639
646
  #
640
647
  # ==== returns
641
648
  # String:: The escaped string.
642
- #
649
+ #
643
650
  # @api private
644
651
  def escape(s)
645
652
  s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
646
653
  '%'+$1.unpack('H2'*$1.size).join('%').upcase
647
654
  }.tr(' ', '+')
648
655
  end
649
-
656
+
650
657
  # ==== Parameter
651
658
  # s<String>:: String to URL unescape.
652
659
  #
653
660
  # ==== returns
654
661
  # String:: The unescaped string.
655
- #
662
+ #
656
663
  # @api private
657
664
  def unescape(s)
658
665
  s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
659
666
  [$1.delete('%')].pack('H*')
660
667
  }
661
668
  end
662
-
669
+
663
670
  # ==== Parameters
664
671
  # query_string<String>:: The query string.
665
672
  # delimiter<String>:: The query string divider. Defaults to "&".
@@ -671,7 +678,7 @@ module Merb
671
678
  # ==== Examples
672
679
  # query_parse("bar=nik&post[body]=heya")
673
680
  # # => { :bar => "nik", :post => { :body => "heya" } }
674
- #
681
+ #
675
682
  # @api private
676
683
  def query_parse(query_string, delimiter = '&;', preserve_order = false)
677
684
  query = preserve_order ? Dictionary.new : {}
@@ -680,19 +687,19 @@ module Merb
680
687
  next if key.nil?
681
688
  if key.include?('[')
682
689
  normalize_params(query, key, value)
683
- else
690
+ else
684
691
  query[key] = value
685
692
  end
686
693
  end
687
694
  preserve_order ? query : query.to_mash
688
695
  end
689
-
696
+
690
697
  NAME_REGEX = /Content-Disposition:.* name="?([^\";]*)"?/ni.freeze
691
698
  CONTENT_TYPE_REGEX = /Content-Type: (.*)\r\n/ni.freeze
692
699
  FILENAME_REGEX = /Content-Disposition:.* filename="?([^\";]*)"?/ni.freeze
693
700
  CRLF = "\r\n".freeze
694
701
  EOL = CRLF
695
-
702
+
696
703
  # ==== Parameters
697
704
  # request<IO>:: The raw request.
698
705
  # boundary<String>:: The boundary string.
@@ -703,7 +710,7 @@ module Merb
703
710
  #
704
711
  # ==== Returns
705
712
  # Hash:: The parsed request.
706
- #
713
+ #
707
714
  # @api private
708
715
  def parse_multipart(request, boundary, content_length)
709
716
  boundary = "--#{boundary}"
@@ -735,19 +742,19 @@ module Merb
735
742
  filename = head[FILENAME_REGEX, 1]
736
743
  content_type = head[CONTENT_TYPE_REGEX, 1]
737
744
  name = head[NAME_REGEX, 1]
738
-
745
+
739
746
  if filename && !filename.empty?
740
747
  body = Tempfile.new(:Merb)
741
748
  body.binmode if defined? body.binmode
742
749
  end
743
750
  next
744
751
  end
745
-
752
+
746
753
  # Save the read body part.
747
754
  if head && (boundary_size+4 < buf.size)
748
755
  body << buf.slice!(0, buf.size - (boundary_size+4))
749
756
  end
750
-
757
+
751
758
  read_size = bufsize < content_length ? bufsize : content_length
752
759
  if( read_size > 0 )
753
760
  c = input.read(read_size)
@@ -756,22 +763,22 @@ module Merb
756
763
  content_length -= c.size
757
764
  end
758
765
  end
759
-
766
+
760
767
  # Save the rest.
761
768
  if i = buf.index(rx)
762
769
  body << buf.slice!(0, i)
763
770
  buf.slice!(0, boundary_size+2)
764
-
771
+
765
772
  content_length = -1 if $1 == "--"
766
773
  end
767
-
768
- if filename && !filename.empty?
774
+
775
+ if filename && !filename.empty?
769
776
  body.rewind
770
- data = {
771
- :filename => File.basename(filename),
772
- :content_type => content_type,
773
- :tempfile => body,
774
- :size => File.size(body.path)
777
+ data = {
778
+ :filename => File.basename(filename),
779
+ :content_type => content_type,
780
+ :tempfile => body,
781
+ :size => File.size(body.path)
775
782
  }
776
783
  else
777
784
  data = body
@@ -781,7 +788,7 @@ module Merb
781
788
  }
782
789
  paramhsh
783
790
  end
784
-
791
+
785
792
  # Converts a query string snippet to a hash and adds it to existing
786
793
  # parameters.
787
794
  #
@@ -792,13 +799,13 @@ module Merb
792
799
  #
793
800
  # ==== Returns
794
801
  # Hash:: Normalized parameters
795
- #
802
+ #
796
803
  # @api private
797
804
  def normalize_params(parms, name, val=nil)
798
805
  name =~ %r([\[\]]*([^\[\]]+)\]*)
799
806
  key = $1 || ''
800
807
  after = $' || ''
801
-
808
+
802
809
  if after == ""
803
810
  parms[key] = val
804
811
  elsif after == "[]"