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.
Potentially problematic release.
This version of rack-contrib might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +11 -0
- data/lib/rack/contrib.rb +0 -2
- data/lib/rack/contrib/jsonp.rb +1 -1
- data/lib/rack/contrib/nested_params.rb +3 -120
- metadata +23 -25
- data/lib/rack/contrib/accept_format.rb +0 -66
- data/lib/rack/contrib/sendfile.rb +0 -138
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b545ac91ebc6596e463da4596aa475e98f170759
|
4
|
+
data.tar.gz: 7185814a488ba9dfc59071569d9ae7175e2f5eb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
data/lib/rack/contrib.rb
CHANGED
@@ -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"
|
data/lib/rack/contrib/jsonp.rb
CHANGED
@@ -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
|
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 '
|
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
|
-
|
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] =
|
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:
|
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-
|
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: '
|
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: '
|
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.
|
75
|
+
version: '0.6'
|
76
76
|
- - ">="
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version: 0.
|
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.
|
85
|
+
version: '0.6'
|
86
86
|
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: 0.
|
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: '
|
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: '
|
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: '
|
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: '
|
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:
|
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
|