webmachine 1.6.0 → 2.0.0.beta

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.
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