webmachine 1.6.0 → 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +2 -5
  4. data/documentation/adapters.md +2 -11
  5. data/examples/debugger.rb +5 -3
  6. data/examples/logging.rb +2 -2
  7. data/examples/webrick.rb +2 -2
  8. data/lib/webmachine/adapter.rb +0 -3
  9. data/lib/webmachine/adapters/lazy_request_body.rb +1 -1
  10. data/lib/webmachine/adapters/rack.rb +38 -34
  11. data/lib/webmachine/adapters/rack_mapped.rb +1 -2
  12. data/lib/webmachine/adapters/webrick.rb +11 -12
  13. data/lib/webmachine/adapters.rb +0 -2
  14. data/lib/webmachine/application.rb +2 -2
  15. data/lib/webmachine/chunked_body.rb +1 -1
  16. data/lib/webmachine/configuration.rb +1 -1
  17. data/lib/webmachine/constants.rb +12 -12
  18. data/lib/webmachine/cookie.rb +20 -18
  19. data/lib/webmachine/decision/conneg.rb +24 -24
  20. data/lib/webmachine/decision/falsey.rb +0 -1
  21. data/lib/webmachine/decision/flow.rb +19 -20
  22. data/lib/webmachine/decision/fsm.rb +4 -4
  23. data/lib/webmachine/decision/helpers.rb +21 -21
  24. data/lib/webmachine/dispatcher/route.rb +28 -28
  25. data/lib/webmachine/dispatcher.rb +3 -2
  26. data/lib/webmachine/errors.rb +7 -8
  27. data/lib/webmachine/etags.rb +2 -1
  28. data/lib/webmachine/header_negotiation.rb +5 -6
  29. data/lib/webmachine/headers.rb +5 -5
  30. data/lib/webmachine/media_type.rb +5 -5
  31. data/lib/webmachine/quoted_string.rb +3 -3
  32. data/lib/webmachine/request.rb +7 -10
  33. data/lib/webmachine/rescueable_exception.rb +3 -3
  34. data/lib/webmachine/resource/authentication.rb +3 -4
  35. data/lib/webmachine/resource/callbacks.rb +3 -3
  36. data/lib/webmachine/resource/encodings.rb +3 -9
  37. data/lib/webmachine/resource.rb +1 -1
  38. data/lib/webmachine/response.rb +7 -9
  39. data/lib/webmachine/spec/adapter_lint.rb +67 -69
  40. data/lib/webmachine/spec/test_resource.rb +22 -22
  41. data/lib/webmachine/streaming/encoder.rb +3 -2
  42. data/lib/webmachine/streaming/io_encoder.rb +4 -3
  43. data/lib/webmachine/trace/fsm.rb +25 -18
  44. data/lib/webmachine/trace/resource_proxy.rb +10 -9
  45. data/lib/webmachine/trace/static/http-headers-status-v3.png +0 -0
  46. data/lib/webmachine/trace/trace_resource.rb +22 -24
  47. data/lib/webmachine/trace.rb +7 -6
  48. data/lib/webmachine/translation.rb +3 -3
  49. data/lib/webmachine/version.rb +1 -1
  50. metadata +52 -86
  51. data/.gitignore +0 -31
  52. data/Gemfile +0 -46
  53. data/Guardfile +0 -11
  54. data/RELEASING.md +0 -21
  55. data/Rakefile +0 -44
  56. data/lib/webmachine/adapters/httpkit.rb +0 -74
  57. data/lib/webmachine/adapters/reel.rb +0 -113
  58. data/memory_test.rb +0 -37
  59. data/spec/spec_helper.rb +0 -56
  60. data/spec/webmachine/adapter_spec.rb +0 -39
  61. data/spec/webmachine/adapters/httpkit_spec.rb +0 -10
  62. data/spec/webmachine/adapters/rack_mapped_spec.rb +0 -71
  63. data/spec/webmachine/adapters/rack_spec.rb +0 -62
  64. data/spec/webmachine/adapters/reel_spec.rb +0 -76
  65. data/spec/webmachine/adapters/webrick_spec.rb +0 -12
  66. data/spec/webmachine/application_spec.rb +0 -74
  67. data/spec/webmachine/chunked_body_spec.rb +0 -30
  68. data/spec/webmachine/configuration_spec.rb +0 -27
  69. data/spec/webmachine/cookie_spec.rb +0 -99
  70. data/spec/webmachine/decision/conneg_spec.rb +0 -166
  71. data/spec/webmachine/decision/falsey_spec.rb +0 -8
  72. data/spec/webmachine/decision/flow_spec.rb +0 -1148
  73. data/spec/webmachine/decision/fsm_spec.rb +0 -163
  74. data/spec/webmachine/decision/helpers_spec.rb +0 -216
  75. data/spec/webmachine/dispatcher/rfc3986_percent_decode_spec.rb +0 -22
  76. data/spec/webmachine/dispatcher/route_spec.rb +0 -248
  77. data/spec/webmachine/dispatcher_spec.rb +0 -104
  78. data/spec/webmachine/errors_spec.rb +0 -13
  79. data/spec/webmachine/etags_spec.rb +0 -75
  80. data/spec/webmachine/events_spec.rb +0 -58
  81. data/spec/webmachine/headers_spec.rb +0 -99
  82. data/spec/webmachine/media_type_spec.rb +0 -85
  83. data/spec/webmachine/request_spec.rb +0 -273
  84. data/spec/webmachine/rescueable_exception_spec.rb +0 -15
  85. data/spec/webmachine/resource/authentication_spec.rb +0 -68
  86. data/spec/webmachine/response_spec.rb +0 -51
  87. data/spec/webmachine/trace/fsm_spec.rb +0 -37
  88. data/spec/webmachine/trace/resource_proxy_spec.rb +0 -34
  89. data/spec/webmachine/trace/trace_store_spec.rb +0 -29
  90. data/spec/webmachine/trace_spec.rb +0 -17
  91. data/webmachine.gemspec +0 -25
@@ -14,7 +14,7 @@ module Webmachine
14
14
  # appropriate media type.
15
15
  # @api private
16
16
  def choose_media_type(provided, header)
17
- types = Array(header).map{|h| h.split(SPLIT_COMMA) }.flatten
17
+ types = Array(header).map { |h| h.split(SPLIT_COMMA) }.flatten
18
18
  requested = MediaTypeList.build(types)
19
19
  provided = provided.map do |p| # normalize_provided
20
20
  MediaType.parse(p)
@@ -43,7 +43,7 @@ module Webmachine
43
43
  # @api private
44
44
  def choose_charset(provided, header)
45
45
  if provided && !provided.empty?
46
- charsets = provided.map {|c| c.first }
46
+ charsets = provided.map { |c| c.first }
47
47
  if charset = do_choose(charsets, header, HAS_ENCODING ? Encoding.default_external.name : kcode_charset)
48
48
  metadata[CHARSET] = charset
49
49
  end
@@ -62,17 +62,17 @@ module Webmachine
62
62
  any_ok = star_priority && star_priority > 0.0
63
63
  accepted = requested.find do |priority, range|
64
64
  if priority == 0.0
65
- provided.delete_if {|tag| language_match(range, tag) }
65
+ provided.delete_if { |tag| language_match(range, tag) }
66
66
  false
67
67
  else
68
- provided.any? {|tag| language_match(range, tag) }
68
+ provided.any? { |tag| language_match(range, tag) }
69
69
  end
70
70
  end
71
71
  chosen = if accepted
72
- provided.find {|tag| language_match(accepted.last, tag) }
73
- elsif any_ok
74
- provided.first
75
- end
72
+ provided.find { |tag| language_match(accepted.last, tag) }
73
+ elsif any_ok
74
+ provided.first
75
+ end
76
76
  if chosen
77
77
  metadata['Language'] = chosen
78
78
  response.headers['Content-Language'] = chosen
@@ -91,14 +91,14 @@ module Webmachine
91
91
  # is "-".
92
92
  # @api private
93
93
  def language_match(range, tag)
94
- range.downcase == tag.downcase || tag =~ /^#{Regexp.escape(range)}\-/i
94
+ range.downcase == tag.downcase || tag =~ /^#{Regexp.escape(range)}-/i
95
95
  end
96
96
 
97
97
  # Makes an conneg choice based what is accepted and what is
98
98
  # provided.
99
99
  # @api private
100
100
  def do_choose(choices, header, default)
101
- choices = choices.dup.map {|s| s.downcase }
101
+ choices = choices.dup.map { |s| s.downcase }
102
102
  accepted = PriorityList.build(header.split(SPLIT_COMMA))
103
103
  default_priority = accepted.priority_of(default)
104
104
  star_priority = accepted.priority_of(STAR)
@@ -112,12 +112,13 @@ module Webmachine
112
112
  choices.include?(acceptable.downcase)
113
113
  end
114
114
  end
115
- (chosen && chosen.last) || # Use the matching one
115
+ chosen&.last || # Use the matching one
116
116
  (any_ok && choices.first) || # Or first if "*"
117
117
  (default_ok && choices.include?(default) && default) # Or default
118
118
  end
119
119
 
120
120
  private
121
+
121
122
  # Matches acceptable items that include 'q' values
122
123
  CONNEG_REGEX = /^\s*(\S+);\s*q=(\S*)\s*$/.freeze
123
124
 
@@ -138,13 +139,13 @@ module Webmachine
138
139
  def kcode_charset
139
140
  case $KCODE
140
141
  when /^U/i
141
- "UTF-8"
142
+ 'UTF-8'
142
143
  when /^S/i
143
- "Shift-JIS"
144
+ 'Shift-JIS'
144
145
  when /^B/i
145
- "Big5"
146
- else #when /^A/i, nil
147
- "ASCII"
146
+ 'Big5'
147
+ else # when /^A/i, nil
148
+ 'ASCII'
148
149
  end
149
150
  end
150
151
 
@@ -157,7 +158,7 @@ module Webmachine
157
158
  # Given an acceptance list, create a PriorityList from them.
158
159
  def self.build(list)
159
160
  new.tap do |plist|
160
- list.each {|item| plist.add_header_val(item) }
161
+ list.each { |item| plist.add_header_val(item) }
161
162
  end
162
163
  end
163
164
 
@@ -166,7 +167,7 @@ module Webmachine
166
167
  # Creates a {PriorityList}.
167
168
  # @see PriorityList::build
168
169
  def initialize
169
- @hash = Hash.new {|h,k| h[k] = [] }
170
+ @hash = Hash.new { |h, k| h[k] = [] }
170
171
  @index = {}
171
172
  end
172
173
 
@@ -185,8 +186,8 @@ module Webmachine
185
186
  def add_header_val(c)
186
187
  if c =~ CONNEG_REGEX
187
188
  choice, q = $1, $2
188
- q = "0" << q if q =~ /^\./ # handle strange FeedBurner Accept
189
- add(q.to_f,choice)
189
+ q = '0' << q if /^\./.match?(q) # handle strange FeedBurner Accept
190
+ add(q.to_f, choice)
190
191
  else
191
192
  add(1.0, c)
192
193
  end
@@ -212,8 +213,8 @@ module Webmachine
212
213
  # @yieldparam [Float] q the acceptable item's priority
213
214
  # @yieldparam [String] v the acceptable item
214
215
  def each
215
- @hash.to_a.sort.reverse_each do |q,l|
216
- l.each {|v| yield q, v }
216
+ @hash.to_a.sort.reverse_each do |q, l|
217
+ l.each { |v| yield q, v }
217
218
  end
218
219
  end
219
220
  end
@@ -232,10 +233,9 @@ module Webmachine
232
233
  q = mt.params.delete('q') || 1.0
233
234
  add(q.to_f, mt)
234
235
  rescue ArgumentError
235
- raise MalformedRequest, t('invalid_media_type', :type => c)
236
+ raise MalformedRequest, t('invalid_media_type', type: c)
236
237
  end
237
238
  end
238
-
239
239
  end # module Conneg
240
240
  end # module Decision
241
241
  end # module Webmachine
@@ -7,4 +7,3 @@ module Webmachine
7
7
  end
8
8
  end
9
9
  end
10
-
@@ -64,7 +64,7 @@ module Webmachine
64
64
  if resource.allowed_methods.include?(request.method)
65
65
  :b9
66
66
  else
67
- response.headers["Allow"] = resource.allowed_methods.join(", ")
67
+ response.headers['Allow'] = resource.allowed_methods.join(', ')
68
68
  405
69
69
  end
70
70
  end
@@ -82,13 +82,13 @@ module Webmachine
82
82
  when true
83
83
  :b9b
84
84
  when false
85
- response.body = "Content-MD5 header does not match request body."
85
+ response.body = 'Content-MD5 header does not match request body.'
86
86
  400
87
87
  else # not_validated
88
88
  if decode64(request.content_md5) == Digest::MD5.hexdigest(request.body)
89
89
  :b9b
90
90
  else
91
- response.body = "Content-MD5 header does not match request body."
91
+ response.body = 'Content-MD5 header does not match request body.'
92
92
  400
93
93
  end
94
94
  end
@@ -123,7 +123,7 @@ module Webmachine
123
123
  CONTENT = /content-/.freeze
124
124
  # Okay Content-* Headers?
125
125
  def b6
126
- decision_test(resource.valid_content_headers?(request.headers.grep(CONTENT)), :b5, 501)
126
+ decision_test(resource.valid_content_headers?(request.headers.grep(CONTENT)), :b5, 501)
127
127
  end
128
128
 
129
129
  # Known Content-Type?
@@ -158,7 +158,7 @@ module Webmachine
158
158
 
159
159
  # Acceptable media type available?
160
160
  def c4
161
- types = resource.content_types_provided.map {|pair| pair.first }
161
+ types = resource.content_types_provided.map { |pair| pair.first }
162
162
  chosen_type = choose_media_type(types, request.accept)
163
163
  if !chosen_type
164
164
  406
@@ -215,7 +215,7 @@ module Webmachine
215
215
  end
216
216
  response.headers[CONTENT_TYPE] = chosen_type.to_s
217
217
  if !request.accept_encoding
218
- choose_encoding(resource.encodings_provided, "identity;q=1.0,*;q=0.5") ? :g7 : 406
218
+ choose_encoding(resource.encodings_provided, 'identity;q=1.0,*;q=0.5') ? :g7 : 406
219
219
  else
220
220
  :f7
221
221
  end
@@ -229,7 +229,7 @@ module Webmachine
229
229
  # Resource exists?
230
230
  def g7
231
231
  # This is the first place after all conneg, so set Vary here
232
- response.headers['Vary'] = variances.join(", ") if variances.any?
232
+ response.headers['Vary'] = variances.join(', ') if variances.any?
233
233
  decision_test(resource.resource_exists?, :g8, :h7)
234
234
  end
235
235
 
@@ -240,12 +240,12 @@ module Webmachine
240
240
 
241
241
  # If-Match: * exists?
242
242
  def g9
243
- quote(request.if_match) == '"*"' ? :h10 : :g11
243
+ (quote(request.if_match) == '"*"') ? :h10 : :g11
244
244
  end
245
245
 
246
246
  # ETag in If-Match
247
247
  def g11
248
- request_etags = request.if_match.split(SPLIT_COMMA).map {|etag| ETag.new(etag) }
248
+ request_etags = request.if_match.split(SPLIT_COMMA).map { |etag| ETag.new(etag) }
249
249
  request_etags.include?(ETag.new(resource.generate_etag)) ? :h10 : 412
250
250
  end
251
251
 
@@ -271,7 +271,7 @@ module Webmachine
271
271
 
272
272
  # Last-Modified > I-UM-S?
273
273
  def h12
274
- resource.last_modified > metadata['If-Unmodified-Since'] ? 412 : :i12
274
+ (resource.last_modified > metadata['If-Unmodified-Since']) ? 412 : :i12
275
275
  end
276
276
 
277
277
  # Moved permanently? (apply PUT to different URI)
@@ -299,7 +299,7 @@ module Webmachine
299
299
 
300
300
  # If-none-match: * exists?
301
301
  def i13
302
- quote(request.if_none_match) == '"*"' ? :j18 : :k13
302
+ (quote(request.if_none_match) == '"*"') ? :j18 : :k13
303
303
  end
304
304
 
305
305
  # GET or HEAD?
@@ -327,10 +327,10 @@ module Webmachine
327
327
 
328
328
  # Etag in if-none-match?
329
329
  def k13
330
- request_etags = request.if_none_match.split(SPLIT_COMMA).map {|etag| ETag.new(etag) }
330
+ request_etags = request.if_none_match.split(SPLIT_COMMA).map { |etag| ETag.new(etag) }
331
331
  resource_etag = resource.generate_etag
332
332
  if resource_etag && request_etags.include?(ETag.new(resource_etag))
333
- :j18
333
+ :j18
334
334
  else
335
335
  :l13
336
336
  end
@@ -371,12 +371,12 @@ module Webmachine
371
371
 
372
372
  # IMS > Now?
373
373
  def l15
374
- metadata['If-Modified-Since'] > Time.now ? :m16 : :l17
374
+ (metadata['If-Modified-Since'] > Time.now) ? :m16 : :l17
375
375
  end
376
376
 
377
377
  # Last-Modified > IMS?
378
378
  def l17
379
- resource.last_modified.nil? || resource.last_modified > metadata['If-Modified-Since'] ? :m16 : 304
379
+ (resource.last_modified.nil? || resource.last_modified > metadata['If-Modified-Since']) ? :m16 : 304
380
380
  end
381
381
 
382
382
  # POST?
@@ -415,7 +415,7 @@ module Webmachine
415
415
  if resource.post_is_create?
416
416
  case uri = resource.create_path
417
417
  when nil
418
- raise InvalidResource, t('create_path_nil', :class => resource.class)
418
+ raise InvalidResource, t('create_path_nil', class: resource.class)
419
419
  when URI, String
420
420
  base_uri = resource.base_uri || request.base_uri
421
421
  new_uri = URI.join(base_uri.to_s, uri)
@@ -431,7 +431,7 @@ module Webmachine
431
431
  when Integer
432
432
  return result
433
433
  else
434
- raise InvalidResource, t('process_post_invalid', :result => result.inspect)
434
+ raise InvalidResource, t('process_post_invalid', result: result.inspect)
435
435
  end
436
436
  end
437
437
  if response.is_redirect?
@@ -471,7 +471,7 @@ module Webmachine
471
471
  if request.get? || request.head?
472
472
  add_caching_headers
473
473
  content_type = metadata[CONTENT_TYPE]
474
- handler = resource.content_types_provided.find {|ct, _| content_type.type_matches?(MediaType.parse(ct)) }.last
474
+ handler = resource.content_types_provided.find { |ct, _| content_type.type_matches?(MediaType.parse(ct)) }.last
475
475
  result = resource.send(handler)
476
476
  if Integer === result
477
477
  result
@@ -507,9 +507,8 @@ module Webmachine
507
507
 
508
508
  # New resource?
509
509
  def p11
510
- !response.headers[LOCATION] ? :o20 : 201
510
+ (!response.headers[LOCATION]) ? :o20 : 201
511
511
  end
512
-
513
512
  end # module Flow
514
513
  end # module Decision
515
514
  end # module Webmachine
@@ -36,11 +36,11 @@ module Webmachine
36
36
  when Symbol # Next state
37
37
  state = result
38
38
  else # You bwoke it
39
- raise InvalidResource, t('fsm_broke', :state => state, :result => result.inspect)
39
+ raise InvalidResource, t('fsm_broke', state: state, result: result.inspect)
40
40
  end
41
41
  end
42
42
  rescue => e
43
- Webmachine.render_error(500, request, response, :message => e.message)
43
+ Webmachine.render_error(500, request, response, message: e.message)
44
44
  ensure
45
45
  trace_response(response)
46
46
  end
@@ -53,11 +53,11 @@ module Webmachine
53
53
  resource.handle_exception(e)
54
54
  500
55
55
  rescue MalformedRequest => e
56
- Webmachine.render_error(400, request, response, :message => e.message)
56
+ Webmachine.render_error(400, request, response, message: e.message)
57
57
  400
58
58
  end
59
59
 
60
- def respond(code, headers={})
60
+ def respond(code, headers = {})
61
61
  response.code = code
62
62
  response.headers.merge!(headers)
63
63
  case code
@@ -31,24 +31,24 @@ module Webmachine
31
31
  body = response.body
32
32
  chosen_charset = metadata[CHARSET]
33
33
  chosen_encoding = metadata[CONTENT_ENCODING]
34
- charsetter = resource.charsets_provided && resource.charsets_provided.find {|c,_| c == chosen_charset }.last || :charset_nop
34
+ charsetter = resource.charsets_provided&.find { |c, _| c == chosen_charset }&.last || :charset_nop
35
35
  encoder = resource.encodings_provided[chosen_encoding]
36
36
  response.body = case body
37
- when String # 1.8 treats Strings as Enumerable
38
- resource.send(encoder, resource.send(charsetter, body))
39
- when IO, StringIO
40
- IOEncoder.new(resource, encoder, charsetter, body)
41
- when Fiber
42
- FiberEncoder.new(resource, encoder, charsetter, body)
43
- when Enumerable
44
- EnumerableEncoder.new(resource, encoder, charsetter, body)
45
- else
46
- if body.respond_to?(:call)
47
- CallableEncoder.new(resource, encoder, charsetter, body)
48
- else
49
- resource.send(encoder, resource.send(charsetter, body))
50
- end
51
- end
37
+ when String # 1.8 treats Strings as Enumerable
38
+ resource.send(encoder, resource.send(charsetter, body))
39
+ when IO, StringIO
40
+ IOEncoder.new(resource, encoder, charsetter, body)
41
+ when Fiber
42
+ FiberEncoder.new(resource, encoder, charsetter, body)
43
+ when Enumerable
44
+ EnumerableEncoder.new(resource, encoder, charsetter, body)
45
+ else
46
+ if body.respond_to?(:call)
47
+ CallableEncoder.new(resource, encoder, charsetter, body)
48
+ else
49
+ resource.send(encoder, resource.send(charsetter, body))
50
+ end
51
+ end
52
52
  if body_is_fixed_length?
53
53
  ensure_content_length(response)
54
54
  else
@@ -60,7 +60,7 @@ module Webmachine
60
60
  # Assists in receiving request bodies
61
61
  def accept_helper
62
62
  content_type = MediaType.parse(request.content_type || 'application/octet-stream')
63
- acceptable = resource.content_types_accepted.find {|ct, _| content_type.match?(ct) }
63
+ acceptable = resource.content_types_accepted.find { |ct, _| content_type.match?(ct) }
64
64
  if acceptable
65
65
  resource.send(acceptable.last)
66
66
  else
@@ -71,10 +71,10 @@ module Webmachine
71
71
  # Computes the entries for the 'Vary' response header
72
72
  def variances
73
73
  resource.variances.tap do |v|
74
- v.unshift "Accept-Language" if resource.languages_provided.size > 1
75
- v.unshift "Accept-Charset" if resource.charsets_provided && resource.charsets_provided.size > 1
76
- v.unshift "Accept-Encoding" if resource.encodings_provided.size > 1
77
- v.unshift "Accept" if resource.content_types_provided.size > 1
74
+ v.unshift 'Accept-Language' if resource.languages_provided.size > 1
75
+ v.unshift 'Accept-Charset' if resource.charsets_provided && resource.charsets_provided.size > 1
76
+ v.unshift 'Accept-Encoding' if resource.encodings_provided.size > 1
77
+ v.unshift 'Accept' if resource.content_types_provided.size > 1
78
78
  end
79
79
  end
80
80
 
@@ -28,6 +28,21 @@ module Webmachine
28
28
  # String version of MATCH_ALL, deprecated. Use the symbol instead.
29
29
  MATCH_ALL_STR = '*'.freeze
30
30
 
31
+ # Decode a string using the scheme described in RFC 3986 2.1. Percent-Encoding (https://www.ietf.org/rfc/rfc3986.txt)
32
+ def self.rfc3986_percent_decode(value)
33
+ s = StringScanner.new(value)
34
+ result = ''
35
+ until s.eos?
36
+ encoded_val = s.scan(/%([0-9a-fA-F]){2}/)
37
+ result << if encoded_val.nil?
38
+ s.getch
39
+ else
40
+ [encoded_val[1..-1]].pack('H*')
41
+ end
42
+ end
43
+ result
44
+ end
45
+
31
46
  # Creates a new Route that will associate a pattern to a
32
47
  # {Resource}.
33
48
  #
@@ -58,25 +73,25 @@ module Webmachine
58
73
  # @yield [req] an optional guard block
59
74
  # @yieldparam [Request] req the request object
60
75
  # @see Dispatcher#add_route
61
- def initialize(path_spec, *args)
62
- if args.last.is_a? Hash
63
- bindings = args.pop
76
+ def initialize(path_spec, *args, &block)
77
+ bindings = if args.last.is_a? Hash
78
+ args.pop
64
79
  else
65
- bindings = {}
80
+ {}
66
81
  end
67
82
 
68
83
  resource = args.pop
69
84
  guards = args
70
- guards << Proc.new if block_given?
85
+ guards << block if block
71
86
 
72
87
  warn t('match_all_symbol') if path_spec.include? MATCH_ALL_STR
73
88
 
74
89
  @path_spec = path_spec
75
- @guards = guards
76
- @resource = resource
77
- @bindings = bindings
90
+ @guards = guards
91
+ @resource = resource
92
+ @bindings = bindings
78
93
 
79
- raise ArgumentError, t('not_resource_class', :class => resource.name) unless resource < Resource
94
+ raise ArgumentError, t('not_resource_class', class: resource.name) unless resource < Resource
80
95
  end
81
96
 
82
97
  # Determines whether the given request matches this route and
@@ -94,11 +109,12 @@ module Webmachine
94
109
  request.disp_path = request.routing_tokens.join(SLASH)
95
110
  request.path_info = @bindings.dup
96
111
  tokens = request.routing_tokens
97
- depth, trailing = bind(tokens, request.path_info)
112
+ _depth, trailing = bind(tokens, request.path_info)
98
113
  request.path_tokens = trailing || []
99
114
  end
100
115
 
101
116
  private
117
+
102
118
  # Attempts to match the path spec against the path tokens, while
103
119
  # accumulating variable bindings.
104
120
  # @param [Array<String>] tokens the list of path segments
@@ -125,9 +141,8 @@ module Webmachine
125
141
  if spec.first.named_captures.empty?
126
142
  bindings[:captures] = (bindings[:captures] || []) + matches.captures
127
143
  else
128
- spec.first.named_captures.reduce(bindings) do |bindings, (name, idxs)|
129
- bindings[name.to_sym] = matches.captures[idxs.first-1]
130
- bindings
144
+ spec.first.named_captures.each_with_object(bindings) do |(name, idxs), bindings|
145
+ bindings[name.to_sym] = matches.captures[idxs.first - 1]
131
146
  end
132
147
  end
133
148
  else
@@ -144,21 +159,6 @@ module Webmachine
144
159
  depth += 1
145
160
  end
146
161
  end
147
-
148
- # Decode a string using the scheme described in RFC 3986 2.1. Percent-Encoding (https://www.ietf.org/rfc/rfc3986.txt)
149
- def self.rfc3986_percent_decode(value)
150
- s = StringScanner.new(value)
151
- result = ''
152
- until s.eos?
153
- encoded_val = s.scan(/%([0-9a-fA-F]){2}/)
154
- result << if encoded_val.nil?
155
- s.getch
156
- else
157
- [encoded_val[1..-1]].pack('H*')
158
- end
159
- end
160
- result
161
- end
162
162
  end # class Route
163
163
  end # module Dispatcher
164
164
  end # module Webmachine
@@ -33,7 +33,7 @@ module Webmachine
33
33
  @routes << route
34
34
  route
35
35
  end
36
- alias :add :add_route
36
+ alias_method :add, :add_route
37
37
 
38
38
  # Dispatches a request to the appropriate {Resource} in the
39
39
  # dispatch list. If a matching resource is not found, a "404 Not
@@ -72,10 +72,11 @@ module Webmachine
72
72
  # Find the first route that matches an incoming request
73
73
  # @param [Request] request the request to match
74
74
  def find_route(request)
75
- @routes.find {|r| r.match?(request) }
75
+ @routes.find { |r| r.match?(request) }
76
76
  end
77
77
 
78
78
  private
79
+
79
80
  def prepare_resource(route, request, response)
80
81
  route.apply(request)
81
82
  @resource_creator.call(route, request, response)
@@ -14,23 +14,22 @@ module Webmachine
14
14
  # @param [Response] req the response object
15
15
  # @param [Hash] options keys to override the defaults when rendering
16
16
  # the response body
17
- def self.render_error(code, req, res, options={})
17
+ def self.render_error(code, req, res, options = {})
18
18
  res.code = code
19
19
  unless res.body
20
20
  title, message = t(["errors.#{code}.title", "errors.#{code}.message"],
21
- { :method => req.method,
22
- :error => res.error}.merge(options))
23
- res.body = t("errors.standard_body",
24
- {:title => title,
25
- :message => message,
26
- :version => Webmachine::SERVER_STRING}.merge(options))
21
+ {method: req.method,
22
+ error: res.error}.merge(options))
23
+ res.body = t('errors.standard_body',
24
+ {title: title,
25
+ message: message,
26
+ version: Webmachine::SERVER_STRING}.merge(options))
27
27
  res.headers[CONTENT_TYPE] = TEXT_HTML
28
28
  end
29
29
  ensure_content_length(res)
30
30
  ensure_date_header(res)
31
31
  end
32
32
 
33
-
34
33
  # Superclass of all errors generated by Webmachine.
35
34
  class Error < ::StandardError; end
36
35
 
@@ -10,7 +10,7 @@ module Webmachine
10
10
 
11
11
  def self.new(etag)
12
12
  return etag if ETag === etag
13
- klass = etag =~ WEAK_ETAG ? WeakETag : self
13
+ klass = WEAK_ETAG.match?(etag) ? WeakETag : self
14
14
  klass.send(:allocate).tap do |obj|
15
15
  obj.send(:initialize, etag)
16
16
  end
@@ -53,6 +53,7 @@ module Webmachine
53
53
  end
54
54
 
55
55
  private
56
+
56
57
  def unquote(str)
57
58
  if str =~ WEAK_ETAG
58
59
  unescape_quotes $1
@@ -3,19 +3,18 @@
3
3
  module Webmachine
4
4
  module HeaderNegotiation
5
5
  def ensure_date_header(res)
6
- if (200..499).include?(res.code)
6
+ if (200..499).cover?(res.code)
7
7
  res.headers[DATE] ||= Time.now.httpdate
8
8
  end
9
9
  end
10
10
 
11
11
  def ensure_content_length(res)
12
12
  body = res.body
13
- case
14
- when res.headers[TRANSFER_ENCODING]
15
- return
16
- when [204, 205, 304].include?(res.code)
13
+ if res.headers[TRANSFER_ENCODING]
14
+ nil
15
+ elsif [204, 205, 304].include?(res.code)
17
16
  res.headers.delete CONTENT_LENGTH
18
- when body != nil
17
+ elsif !body.nil?
19
18
  res.headers[CONTENT_LENGTH] = body.respond_to?(:bytesize) ? body.bytesize.to_s : body.length.to_s
20
19
  else
21
20
  res.headers[CONTENT_LENGTH] = '0'
@@ -10,11 +10,10 @@ module Webmachine
10
10
  # @param [Hash] env a hash of CGI-style env/headers
11
11
  # @return [Webmachine::Headers]
12
12
  def self.from_cgi(env)
13
- env.inject(new) do |h,(k,v)|
13
+ env.each_with_object(new) do |(k, v), h|
14
14
  if k =~ CGI_HTTP_MATCH || k =~ CONTENT_TYPE_LENGTH_MATCH
15
15
  h[$1.tr(UNDERSCORE, DASH)] = v
16
16
  end
17
- h
18
17
  end
19
18
  end
20
19
 
@@ -33,7 +32,7 @@ module Webmachine
33
32
  # @param [Object]
34
33
  # @return [Webmachine::Headers]
35
34
  def self.[](*args)
36
- super(super(*args).map {|k, v| [k.to_s.downcase, v]})
35
+ super(super(*args).map { |k, v| [k.to_s.downcase, v] })
37
36
  end
38
37
 
39
38
  # Fetch a header
@@ -42,7 +41,7 @@ module Webmachine
42
41
  end
43
42
 
44
43
  # Set a header
45
- def []=(key,value)
44
+ def []=(key, value)
46
45
  super transform_key(key), value
47
46
  end
48
47
 
@@ -76,10 +75,11 @@ module Webmachine
76
75
 
77
76
  # Select matching headers
78
77
  def grep(pattern)
79
- self.class[select { |k,_| pattern === k }]
78
+ self.class[select { |k, _| pattern === k }]
80
79
  end
81
80
 
82
81
  private
82
+
83
83
  def transform_key(key)
84
84
  key.to_s.downcase
85
85
  end