rack-contrib 1.8.0 → 2.0.0

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.

Potentially problematic release.


This version of rack-contrib might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bee6a82e9e3cd0238bfc695f9d18a74045235f86
4
- data.tar.gz: a340facd62eb27f47bbce5e5e02f15c949454946
3
+ metadata.gz: b545ac91ebc6596e463da4596aa475e98f170759
4
+ data.tar.gz: 7185814a488ba9dfc59071569d9ae7175e2f5eb3
5
5
  SHA512:
6
- metadata.gz: 6f3bee839cd6955789228948379912610ac8c9ea8dd2cfd2339f43b2e15e311ee0aacd65f71304977c2fb78624cd374a1b8e071e9129da0db2cde9e61828b64a
7
- data.tar.gz: 5c0ce1dc50158e6790db66d758f7a9a16f6d5b0fa87a50f759e00c17d9a7ea5226ebc16e275f3f9e687306867d937bf1cadff224f763481f0991aa0650b58dc2
6
+ metadata.gz: 6b8b85e0c0d7541825991235ec8b20057d9d8965d031540f056741fb99b9bd6ac524096988066ba717221ec6f6f134db76f9bf5f6325794f28d6a8f2b8831a0f
7
+ data.tar.gz: 3413f89de71509f68b16b21d4e40dc0eb7fbd98c5210a5fa9e0512521f630f044a75933ce05eca29f19536f052184722c79ca37ba443d49f8161a3702054ac40
data/README.md CHANGED
@@ -61,6 +61,17 @@ use Rack::MailExceptions
61
61
  run theapp
62
62
  ```
63
63
 
64
+ #### Versioning
65
+
66
+ This package is [semver compliant](https://semver.org); you should use a
67
+ pessimistic version constraint (`~>`) against the relevant `2.x` version of
68
+ this gem.
69
+
70
+ This version of `rack-contrib` is only compatible with `rack` 2.x. If you
71
+ are using `rack` 1.x, you will need to use `rack-contrib` 1.x. A suitable
72
+ pessimistic version constraint (`~>`) is recommended.
73
+
74
+
64
75
  ### Testing
65
76
 
66
77
  To contribute to the project, begin by cloning the repo and installing the necessary gems:
@@ -14,7 +14,6 @@ module Rack
14
14
  end
15
15
  end
16
16
 
17
- autoload :AcceptFormat, "rack/contrib/accept_format"
18
17
  autoload :Access, "rack/contrib/access"
19
18
  autoload :BounceFavicon, "rack/contrib/bounce_favicon"
20
19
  autoload :Cookies, "rack/contrib/cookies"
@@ -34,7 +33,6 @@ module Rack
34
33
  autoload :Profiler, "rack/contrib/profiler"
35
34
  autoload :ResponseHeaders, "rack/contrib/response_headers"
36
35
  autoload :Runtime, "rack/contrib/runtime"
37
- autoload :Sendfile, "rack/contrib/sendfile"
38
36
  autoload :Signals, "rack/contrib/signals"
39
37
  autoload :SimpleEndpoint, "rack/contrib/simple_endpoint"
40
38
  autoload :TimeZone, "rack/contrib/time_zone"
@@ -53,7 +53,7 @@ module Rack
53
53
 
54
54
  # Set new Content-Length, if it was set before we mutated the response body
55
55
  if headers['Content-Length']
56
- length = response.to_ary.inject(0) { |len, part| len + bytesize(part) }
56
+ length = response.to_ary.inject(0) { |len, part| len + part.bytesize }
57
57
  headers['Content-Length'] = length.to_s
58
58
  end
59
59
  end
@@ -1,5 +1,4 @@
1
- require 'cgi'
2
- require 'strscan'
1
+ require 'rack/utils'
3
2
 
4
3
  module Rack
5
4
  # Rack middleware for parsing POST/PUT body data into nested parameters
@@ -20,130 +19,14 @@ module Rack
20
19
 
21
20
  def call(env)
22
21
  if form_vars = env[FORM_VARS]
23
- env[FORM_HASH] = parse_query_parameters(form_vars)
22
+ Rack::Utils.parse_nested_query(form_vars)
24
23
  elsif env[CONTENT_TYPE] == URL_ENCODED
25
24
  post_body = env[POST_BODY]
26
25
  env[FORM_INPUT] = post_body
27
- env[FORM_HASH] = parse_query_parameters(post_body.read)
26
+ env[FORM_HASH] = Rack::Utils.parse_nested_query(post_body.read)
28
27
  post_body.rewind if post_body.respond_to?(:rewind)
29
28
  end
30
29
  @app.call(env)
31
30
  end
32
-
33
- ## the rest is nabbed from Rails ##
34
-
35
- def parse_query_parameters(query_string)
36
- return {} if query_string.nil? or query_string.empty?
37
-
38
- pairs = query_string.split('&').collect do |chunk|
39
- next if chunk.empty?
40
- key, value = chunk.split('=', 2)
41
- next if key.empty?
42
- value = value.nil? ? nil : CGI.unescape(value)
43
- [ CGI.unescape(key), value ]
44
- end.compact
45
-
46
- UrlEncodedPairParser.new(pairs).result
47
- end
48
-
49
- class UrlEncodedPairParser < StringScanner
50
- attr_reader :top, :parent, :result
51
-
52
- def initialize(pairs = [])
53
- super('')
54
- @result = {}
55
- pairs.each { |key, value| parse(key, value) }
56
- end
57
-
58
- KEY_REGEXP = %r{([^\[\]=&]+)}
59
- BRACKETED_KEY_REGEXP = %r{\[([^\[\]=&]+)\]}
60
-
61
- # Parse the query string
62
- def parse(key, value)
63
- self.string = key
64
- @top, @parent = result, nil
65
-
66
- # First scan the bare key
67
- key = scan(KEY_REGEXP) or return
68
- key = post_key_check(key)
69
-
70
- # Then scan as many nestings as present
71
- until eos?
72
- r = scan(BRACKETED_KEY_REGEXP) or return
73
- key = self[1]
74
- key = post_key_check(key)
75
- end
76
-
77
- bind(key, value)
78
- end
79
-
80
- private
81
- # After we see a key, we must look ahead to determine our next action. Cases:
82
- #
83
- # [] follows the key. Then the value must be an array.
84
- # = follows the key. (A value comes next)
85
- # & or the end of string follows the key. Then the key is a flag.
86
- # otherwise, a hash follows the key.
87
- def post_key_check(key)
88
- if scan(/\[\]/) # a[b][] indicates that b is an array
89
- container(key, Array)
90
- nil
91
- elsif check(/\[[^\]]/) # a[b] indicates that a is a hash
92
- container(key, Hash)
93
- nil
94
- else # End of key? We do nothing.
95
- key
96
- end
97
- end
98
-
99
- # Add a container to the stack.
100
- def container(key, klass)
101
- type_conflict! klass, top[key] if top.is_a?(Hash) && top.key?(key) && ! top[key].is_a?(klass)
102
- value = bind(key, klass.new)
103
- type_conflict! klass, value unless value.is_a?(klass)
104
- push(value)
105
- end
106
-
107
- # Push a value onto the 'stack', which is actually only the top 2 items.
108
- def push(value)
109
- @parent, @top = @top, value
110
- end
111
-
112
- # Bind a key (which may be nil for items in an array) to the provided value.
113
- def bind(key, value)
114
- if top.is_a? Array
115
- if key
116
- if top[-1].is_a?(Hash) && ! top[-1].key?(key)
117
- top[-1][key] = value
118
- else
119
- top << {key => value}
120
- end
121
- push top.last
122
- return top[key]
123
- else
124
- top << value
125
- return value
126
- end
127
- elsif top.is_a? Hash
128
- key = CGI.unescape(key)
129
- parent << (@top = {}) if top.key?(key) && parent.is_a?(Array)
130
-
131
- if top.include?(key) && value.is_a?(String)
132
- warn "Rack::NestedParams' parsing behavior will change in rack-contrib 2.0"
133
- warn "Currently 'foo=1&foo=2' is parsed to {'foo' => '1'}, in 2.0 it will be parsed to {'foo' => '2'}"
134
- end
135
-
136
- top[key] ||= value
137
- return top[key]
138
- else
139
- raise ArgumentError, "Don't know what to do: top is #{top.inspect}"
140
- end
141
- end
142
-
143
- def type_conflict!(klass, value)
144
- raise TypeError, "Conflicting types for parameter containers. Expected an instance of #{klass} but found an instance of #{value.class}. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value. (The parameters received were #{value.inspect}.)"
145
- end
146
- end
147
-
148
31
  end
149
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-contrib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rack-devel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-08 00:00:00.000000000 Z
11
+ date: 2017-11-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.4'
19
+ version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.4'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -72,54 +72,48 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0.5'
75
+ version: '0.6'
76
76
  - - ">="
77
77
  - !ruby/object:Gem::Version
78
- version: 0.5.2
78
+ version: 0.6.8
79
79
  type: :development
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
83
  - - "~>"
84
84
  - !ruby/object:Gem::Version
85
- version: '0.5'
85
+ version: '0.6'
86
86
  - - ">="
87
87
  - !ruby/object:Gem::Version
88
- version: 0.5.2
88
+ version: 0.6.8
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: json
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: '1.8'
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: 1.8.5
95
+ version: '2.0'
99
96
  type: :development
100
97
  prerelease: false
101
98
  version_requirements: !ruby/object:Gem::Requirement
102
99
  requirements:
103
100
  - - "~>"
104
101
  - !ruby/object:Gem::Version
105
- version: '1.8'
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- version: 1.8.5
102
+ version: '2.0'
109
103
  - !ruby/object:Gem::Dependency
110
104
  name: mime-types
111
105
  requirement: !ruby/object:Gem::Requirement
112
106
  requirements:
113
- - - "<"
107
+ - - "~>"
114
108
  - !ruby/object:Gem::Version
115
- version: '3'
109
+ version: '3.0'
116
110
  type: :development
117
111
  prerelease: false
118
112
  version_requirements: !ruby/object:Gem::Requirement
119
113
  requirements:
120
- - - "<"
114
+ - - "~>"
121
115
  - !ruby/object:Gem::Version
122
- version: '3'
116
+ version: '3.0'
123
117
  - !ruby/object:Gem::Dependency
124
118
  name: minitest
125
119
  requirement: !ruby/object:Gem::Requirement
@@ -155,6 +149,9 @@ dependencies:
155
149
  - - "~>"
156
150
  - !ruby/object:Gem::Version
157
151
  version: '2.3'
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: 2.6.4
158
155
  type: :development
159
156
  prerelease: false
160
157
  version_requirements: !ruby/object:Gem::Requirement
@@ -162,6 +159,9 @@ dependencies:
162
159
  - - "~>"
163
160
  - !ruby/object:Gem::Version
164
161
  version: '2.3'
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: 2.6.4
165
165
  - !ruby/object:Gem::Dependency
166
166
  name: nbio-csshttprequest
167
167
  requirement: !ruby/object:Gem::Requirement
@@ -202,14 +202,14 @@ dependencies:
202
202
  requirements:
203
203
  - - "~>"
204
204
  - !ruby/object:Gem::Version
205
- version: '3.12'
205
+ version: '5.0'
206
206
  type: :development
207
207
  prerelease: false
208
208
  version_requirements: !ruby/object:Gem::Requirement
209
209
  requirements:
210
210
  - - "~>"
211
211
  - !ruby/object:Gem::Version
212
- version: '3.12'
212
+ version: '5.0'
213
213
  - !ruby/object:Gem::Dependency
214
214
  name: ruby-prof
215
215
  requirement: !ruby/object:Gem::Requirement
@@ -236,7 +236,6 @@ files:
236
236
  - COPYING
237
237
  - README.md
238
238
  - lib/rack/contrib.rb
239
- - lib/rack/contrib/accept_format.rb
240
239
  - lib/rack/contrib/access.rb
241
240
  - lib/rack/contrib/backstage.rb
242
241
  - lib/rack/contrib/bounce_favicon.rb
@@ -267,7 +266,6 @@ files:
267
266
  - lib/rack/contrib/response_headers.rb
268
267
  - lib/rack/contrib/route_exceptions.rb
269
268
  - lib/rack/contrib/runtime.rb
270
- - lib/rack/contrib/sendfile.rb
271
269
  - lib/rack/contrib/signals.rb
272
270
  - lib/rack/contrib/simple_endpoint.rb
273
271
  - lib/rack/contrib/static_cache.rb
@@ -291,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
291
289
  requirements:
292
290
  - - ">="
293
291
  - !ruby/object:Gem::Version
294
- version: '0'
292
+ version: 2.2.2
295
293
  required_rubygems_version: !ruby/object:Gem::Requirement
296
294
  requirements:
297
295
  - - ">="
@@ -1,66 +0,0 @@
1
- module Rack
2
- #
3
- # CAUTION: THIS MIDDLEWARE IS DEPRECATED. DO NOT USE IT.
4
- #
5
- # This middleware is slated for removal as of rack-contrib 2.0.0, because
6
- # it is terribad. Applications should *always* use the `Accept` header to
7
- # detect response formats (when it is available), rather than ignoring
8
- # that and instead examining the extension of the request. We recommend
9
- # using the `rack-accept` gem for handling the `Accept` family of entity
10
- # request headers.
11
- #
12
- # A Rack middleware for automatically adding a <tt>format</tt> token at the end of the request path
13
- # when there is none. It can detect formats passed in the HTTP_ACCEPT header to populate this token.
14
- #
15
- # e.g.:
16
- # GET /some/resource HTTP/1.1
17
- # Accept: application/json
18
- # ->
19
- # GET /some/resource.json HTTP/1.1
20
- # Accept: application/json
21
- #
22
- # You can add custom types with this kind of function (taken from sinatra):
23
- # def mime(ext, type)
24
- # ext = ".#{ext}" unless ext.to_s[0] == ?.
25
- # Rack::Mime::MIME_TYPES[ext.to_s] = type
26
- # end
27
- # and then:
28
- # mime :json, 'application/json'
29
- #
30
- # Note: it does not take into account multiple media types in the Accept header.
31
- # The first media type takes precedence over all the others.
32
- #
33
- # MIT-License - Cyril Rohr
34
- #
35
- class AcceptFormat
36
- def self.deprecation_acknowledged
37
- @deprecation_acknowledged
38
- end
39
-
40
- def self.acknowledge_deprecation
41
- @deprecation_acknowledged = true
42
- end
43
-
44
- def initialize(app, default_extention = '.html')
45
- unless self.class.deprecation_acknowledged
46
- warn "Rack::AcceptFormat is DEPRECATED and will be removed in rack-contrib 2.0.0"
47
- warn "Please see this middleware's documentation for more info."
48
- end
49
- @ext = default_extention.to_s.strip
50
- @ext = ".#{@ext}" unless @ext[0] == ?.
51
- @app = app
52
- end
53
-
54
- def call(env)
55
- req = Rack::Request.new(env)
56
-
57
- if ::File.extname(req.path_info).empty?
58
- accept = env['HTTP_ACCEPT'].to_s.scan(/[^;,\s]*\/[^;,\s]*/)[0].to_s
59
- extension = Rack::Mime::MIME_TYPES.invert[accept] || @ext
60
- req.path_info = req.path_info.chomp('/') << "#{extension}"
61
- end
62
-
63
- @app.call(env)
64
- end
65
- end
66
- end
@@ -1,138 +0,0 @@
1
- require 'rack/file'
2
-
3
- warn "rack-contrib deprecation warning: the rack-contrib version of Rack::Sendfile is deprecated and will be removed in rack-contrib 2.0. Please use the Rack::Sendfile from Rack 2.x instead."
4
-
5
- module Rack
6
-
7
- #
8
- # The Sendfile middleware intercepts responses whose body is being
9
- # served from a file and replaces it with a server specific X-Sendfile
10
- # header. The web server is then responsible for writing the file contents
11
- # to the client. This can dramatically reduce the amount of work required
12
- # by the Ruby backend and takes advantage of the web servers optimized file
13
- # delivery code.
14
- #
15
- # In order to take advantage of this middleware, the response body must
16
- # respond to +to_path+ and the request must include an X-Sendfile-Type
17
- # header. Rack::File and other components implement +to_path+ so there's
18
- # rarely anything you need to do in your application. The X-Sendfile-Type
19
- # header is typically set in your web servers configuration. The following
20
- # sections attempt to document
21
- #
22
- # === Nginx
23
- #
24
- # Nginx supports the X-Accel-Redirect header. This is similar to X-Sendfile
25
- # but requires parts of the filesystem to be mapped into a private URL
26
- # hierarachy.
27
- #
28
- # The following example shows the Nginx configuration required to create
29
- # a private "/files/" area, enable X-Accel-Redirect, and pass the special
30
- # X-Sendfile-Type and X-Accel-Mapping headers to the backend:
31
- #
32
- # location /files/ {
33
- # internal;
34
- # alias /var/www/;
35
- # }
36
- #
37
- # location / {
38
- # proxy_redirect false;
39
- #
40
- # proxy_set_header Host $host;
41
- # proxy_set_header X-Real-IP $remote_addr;
42
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
43
- #
44
- # proxy_set_header X-Sendfile-Type X-Accel-Redirect
45
- # proxy_set_header X-Accel-Mapping /files/=/var/www/;
46
- #
47
- # proxy_pass http://127.0.0.1:8080/;
48
- # }
49
- #
50
- # Note that the X-Sendfile-Type header must be set exactly as shown above. The
51
- # X-Accel-Mapping header should specify the name of the private URL pattern,
52
- # followed by an equals sign (=), followed by the location on the file system
53
- # that it maps to. The middleware performs a simple substitution on the
54
- # resulting path.
55
- #
56
- # See Also: http://wiki.codemongers.com/NginxXSendfile
57
- #
58
- # === lighttpd
59
- #
60
- # Lighttpd has supported some variation of the X-Sendfile header for some
61
- # time, although only recent version support X-Sendfile in a reverse proxy
62
- # configuration.
63
- #
64
- # $HTTP["host"] == "example.com" {
65
- # proxy-core.protocol = "http"
66
- # proxy-core.balancer = "round-robin"
67
- # proxy-core.backends = (
68
- # "127.0.0.1:8000",
69
- # "127.0.0.1:8001",
70
- # ...
71
- # )
72
- #
73
- # proxy-core.allow-x-sendfile = "enable"
74
- # proxy-core.rewrite-request = (
75
- # "X-Sendfile-Type" => (".*" => "X-Sendfile")
76
- # )
77
- # }
78
- #
79
- # See Also: http://redmine.lighttpd.net/wiki/lighttpd/Docs:ModProxyCore
80
- #
81
- # === Apache
82
- #
83
- # X-Sendfile is supported under Apache 2.x using a separate module:
84
- #
85
- # http://tn123.ath.cx/mod_xsendfile/
86
- #
87
- # Once the module is compiled and installed, you can enable it using
88
- # XSendFile config directive:
89
- #
90
- # RequestHeader Set X-Sendfile-Type X-Sendfile
91
- # ProxyPassReverse / http://localhost:8001/
92
- # XSendFile on
93
-
94
- class Sendfile
95
- def initialize(app, variation=nil)
96
- @app = app
97
- @variation = variation
98
- end
99
-
100
- def call(env)
101
- status, headers, body = @app.call(env)
102
- if body.respond_to?(:to_path)
103
- case type = variation(env)
104
- when 'X-Accel-Redirect'
105
- path = ::File.expand_path(body.to_path)
106
- if url = map_accel_path(env, path)
107
- headers[type] = url
108
- body = []
109
- else
110
- env['rack.errors'] << "X-Accel-Mapping header missing"
111
- end
112
- when 'X-Sendfile', 'X-Lighttpd-Send-File'
113
- path = ::File.expand_path(body.to_path)
114
- headers[type] = path
115
- body = []
116
- when '', nil
117
- else
118
- env['rack.errors'] << "Unknown x-sendfile variation: '#{variation}'.\n"
119
- end
120
- end
121
- [status, headers, body]
122
- end
123
-
124
- private
125
- def variation(env)
126
- @variation ||
127
- env['sendfile.type'] ||
128
- env['HTTP_X_SENDFILE_TYPE']
129
- end
130
-
131
- def map_accel_path(env, file)
132
- if mapping = env['HTTP_X_ACCEL_MAPPING']
133
- internal, external = mapping.split('=', 2).map{ |p| p.strip }
134
- file.sub(/^#{internal}/i, external)
135
- end
136
- end
137
- end
138
- end