merb-core 0.9.9 → 0.9.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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 == "[]"