rack-contrib 1.8.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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