rack 2.0.9.3 → 3.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 might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +808 -0
- data/CONTRIBUTING.md +142 -0
- data/{COPYING → MIT-LICENSE} +4 -2
- data/README.md +293 -0
- data/SPEC.rdoc +340 -0
- data/lib/rack/auth/abstract/handler.rb +6 -2
- data/lib/rack/auth/abstract/request.rb +4 -2
- data/lib/rack/auth/basic.rb +7 -4
- data/lib/rack/auth/digest/md5.rb +1 -129
- data/lib/rack/auth/digest/nonce.rb +1 -51
- data/lib/rack/auth/digest/params.rb +1 -52
- data/lib/rack/auth/digest/request.rb +1 -41
- data/lib/rack/auth/digest.rb +256 -0
- data/lib/rack/body_proxy.rb +18 -15
- data/lib/rack/builder.rb +151 -40
- data/lib/rack/cascade.rb +30 -12
- data/lib/rack/chunked.rb +74 -23
- data/lib/rack/common_logger.rb +49 -36
- data/lib/rack/conditional_get.rb +33 -26
- data/lib/rack/config.rb +2 -0
- data/lib/rack/constants.rb +63 -0
- data/lib/rack/content_length.rb +13 -16
- data/lib/rack/content_type.rb +12 -8
- data/lib/rack/deflater.rb +84 -45
- data/lib/rack/directory.rb +90 -64
- data/lib/rack/etag.rb +17 -23
- data/lib/rack/events.rb +23 -20
- data/lib/rack/file.rb +5 -172
- data/lib/rack/files.rb +216 -0
- data/lib/rack/head.rb +10 -9
- data/lib/rack/headers.rb +154 -0
- data/lib/rack/lint.rb +786 -645
- data/lib/rack/lock.rb +4 -6
- data/lib/rack/logger.rb +4 -0
- data/lib/rack/media_type.rb +10 -5
- data/lib/rack/method_override.rb +8 -2
- data/lib/rack/mime.rb +17 -1
- data/lib/rack/mock.rb +2 -195
- data/lib/rack/mock_request.rb +166 -0
- data/lib/rack/mock_response.rb +126 -0
- data/lib/rack/multipart/generator.rb +21 -15
- data/lib/rack/multipart/parser.rb +161 -118
- data/lib/rack/multipart/uploaded_file.rb +19 -7
- data/lib/rack/multipart.rb +23 -41
- data/lib/rack/null_logger.rb +11 -0
- data/lib/rack/query_parser.rb +126 -65
- data/lib/rack/recursive.rb +9 -5
- data/lib/rack/reloader.rb +6 -4
- data/lib/rack/request.rb +331 -74
- data/lib/rack/response.rb +223 -70
- data/lib/rack/rewindable_input.rb +28 -8
- data/lib/rack/runtime.rb +11 -8
- data/lib/rack/sendfile.rb +42 -33
- data/lib/rack/show_exceptions.rb +35 -18
- data/lib/rack/show_status.rb +25 -15
- data/lib/rack/static.rb +30 -18
- data/lib/rack/tempfile_reaper.rb +16 -5
- data/lib/rack/urlmap.rb +14 -6
- data/lib/rack/utils.rb +268 -260
- data/lib/rack/version.rb +34 -0
- data/lib/rack.rb +15 -92
- metadata +44 -207
- data/HISTORY.md +0 -520
- data/README.rdoc +0 -316
- data/Rakefile +0 -116
- data/SPEC +0 -263
- data/bin/rackup +0 -4
- data/contrib/rack.png +0 -0
- data/contrib/rack.svg +0 -150
- data/contrib/rack_logo.svg +0 -164
- data/contrib/rdoc.css +0 -412
- data/example/lobster.ru +0 -4
- data/example/protectedlobster.rb +0 -14
- data/example/protectedlobster.ru +0 -8
- data/lib/rack/handler/cgi.rb +0 -60
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -70
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -120
- data/lib/rack/handler.rb +0 -99
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -395
- data/lib/rack/session/abstract/id.rb +0 -510
- data/lib/rack/session/cookie.rb +0 -204
- data/lib/rack/session/memcache.rb +0 -99
- data/lib/rack/session/pool.rb +0 -83
- data/rack.gemspec +0 -34
- data/test/builder/an_underscore_app.rb +0 -5
- data/test/builder/anything.rb +0 -5
- data/test/builder/comment.ru +0 -4
- data/test/builder/end.ru +0 -5
- data/test/builder/line.ru +0 -1
- data/test/builder/options.ru +0 -2
- data/test/cgi/assets/folder/test.js +0 -1
- data/test/cgi/assets/fonts/font.eot +0 -1
- data/test/cgi/assets/images/image.png +0 -1
- data/test/cgi/assets/index.html +0 -1
- data/test/cgi/assets/javascripts/app.js +0 -1
- data/test/cgi/assets/stylesheets/app.css +0 -1
- data/test/cgi/lighttpd.conf +0 -26
- data/test/cgi/rackup_stub.rb +0 -6
- data/test/cgi/sample_rackup.ru +0 -5
- data/test/cgi/test +0 -9
- data/test/cgi/test+directory/test+file +0 -1
- data/test/cgi/test.fcgi +0 -9
- data/test/cgi/test.gz +0 -0
- data/test/cgi/test.ru +0 -5
- data/test/gemloader.rb +0 -10
- data/test/helper.rb +0 -34
- data/test/multipart/bad_robots +0 -259
- data/test/multipart/binary +0 -0
- data/test/multipart/content_type_and_no_filename +0 -6
- data/test/multipart/empty +0 -10
- data/test/multipart/fail_16384_nofile +0 -814
- data/test/multipart/file1.txt +0 -1
- data/test/multipart/filename_and_modification_param +0 -7
- data/test/multipart/filename_and_no_name +0 -6
- data/test/multipart/filename_with_encoded_words +0 -7
- data/test/multipart/filename_with_escaped_quotes +0 -6
- data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
- data/test/multipart/filename_with_null_byte +0 -7
- data/test/multipart/filename_with_percent_escaped_quotes +0 -6
- data/test/multipart/filename_with_single_quote +0 -7
- data/test/multipart/filename_with_unescaped_percentages +0 -6
- data/test/multipart/filename_with_unescaped_percentages2 +0 -6
- data/test/multipart/filename_with_unescaped_percentages3 +0 -6
- data/test/multipart/filename_with_unescaped_quotes +0 -6
- data/test/multipart/ie +0 -6
- data/test/multipart/invalid_character +0 -6
- data/test/multipart/mixed_files +0 -21
- data/test/multipart/nested +0 -10
- data/test/multipart/none +0 -9
- data/test/multipart/quoted +0 -15
- data/test/multipart/rack-logo.png +0 -0
- data/test/multipart/semicolon +0 -6
- data/test/multipart/text +0 -15
- data/test/multipart/three_files_three_fields +0 -31
- data/test/multipart/unity3d_wwwform +0 -11
- data/test/multipart/webkit +0 -32
- data/test/rackup/config.ru +0 -31
- data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
- data/test/spec_auth_basic.rb +0 -89
- data/test/spec_auth_digest.rb +0 -260
- data/test/spec_body_proxy.rb +0 -85
- data/test/spec_builder.rb +0 -233
- data/test/spec_cascade.rb +0 -63
- data/test/spec_cgi.rb +0 -84
- data/test/spec_chunked.rb +0 -103
- data/test/spec_common_logger.rb +0 -107
- data/test/spec_conditional_get.rb +0 -103
- data/test/spec_config.rb +0 -23
- data/test/spec_content_length.rb +0 -86
- data/test/spec_content_type.rb +0 -46
- data/test/spec_deflater.rb +0 -375
- data/test/spec_directory.rb +0 -148
- data/test/spec_etag.rb +0 -108
- data/test/spec_events.rb +0 -133
- data/test/spec_fastcgi.rb +0 -85
- data/test/spec_file.rb +0 -264
- data/test/spec_handler.rb +0 -57
- data/test/spec_head.rb +0 -46
- data/test/spec_lint.rb +0 -520
- data/test/spec_lobster.rb +0 -59
- data/test/spec_lock.rb +0 -204
- data/test/spec_logger.rb +0 -24
- data/test/spec_media_type.rb +0 -42
- data/test/spec_method_override.rb +0 -110
- data/test/spec_mime.rb +0 -51
- data/test/spec_mock.rb +0 -359
- data/test/spec_multipart.rb +0 -721
- data/test/spec_null_logger.rb +0 -21
- data/test/spec_recursive.rb +0 -75
- data/test/spec_request.rb +0 -1423
- data/test/spec_response.rb +0 -528
- data/test/spec_rewindable_input.rb +0 -128
- data/test/spec_runtime.rb +0 -50
- data/test/spec_sendfile.rb +0 -125
- data/test/spec_server.rb +0 -193
- data/test/spec_session_abstract_id.rb +0 -31
- data/test/spec_session_abstract_session_hash.rb +0 -45
- data/test/spec_session_cookie.rb +0 -442
- data/test/spec_session_memcache.rb +0 -357
- data/test/spec_session_persisted_secure_secure_session_hash.rb +0 -73
- data/test/spec_session_pool.rb +0 -247
- data/test/spec_show_exceptions.rb +0 -93
- data/test/spec_show_status.rb +0 -104
- data/test/spec_static.rb +0 -184
- data/test/spec_tempfile_reaper.rb +0 -64
- data/test/spec_thin.rb +0 -96
- data/test/spec_urlmap.rb +0 -237
- data/test/spec_utils.rb +0 -742
- data/test/spec_version.rb +0 -11
- data/test/spec_webrick.rb +0 -206
- data/test/static/another/index.html +0 -1
- data/test/static/foo.html +0 -1
- data/test/static/index.html +0 -1
- data/test/testrequest.rb +0 -78
- data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
- data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/lib/rack/sendfile.rb
CHANGED
@@ -1,33 +1,36 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'constants'
|
4
|
+
require_relative 'utils'
|
5
|
+
require_relative 'body_proxy'
|
3
6
|
|
4
7
|
module Rack
|
5
8
|
|
6
9
|
# = Sendfile
|
7
10
|
#
|
8
11
|
# The Sendfile middleware intercepts responses whose body is being
|
9
|
-
# served from a file and replaces it with a server specific
|
12
|
+
# served from a file and replaces it with a server specific x-sendfile
|
10
13
|
# header. The web server is then responsible for writing the file contents
|
11
14
|
# to the client. This can dramatically reduce the amount of work required
|
12
15
|
# by the Ruby backend and takes advantage of the web server's optimized file
|
13
16
|
# delivery code.
|
14
17
|
#
|
15
18
|
# In order to take advantage of this middleware, the response body must
|
16
|
-
# respond to +to_path+ and the request must include an
|
17
|
-
# header. Rack::
|
18
|
-
# rarely anything you need to do in your application. The
|
19
|
+
# respond to +to_path+ and the request must include an x-sendfile-type
|
20
|
+
# header. Rack::Files and other components implement +to_path+ so there's
|
21
|
+
# rarely anything you need to do in your application. The x-sendfile-type
|
19
22
|
# header is typically set in your web servers configuration. The following
|
20
23
|
# sections attempt to document
|
21
24
|
#
|
22
25
|
# === Nginx
|
23
26
|
#
|
24
|
-
# Nginx supports the
|
27
|
+
# Nginx supports the x-accel-redirect header. This is similar to x-sendfile
|
25
28
|
# but requires parts of the filesystem to be mapped into a private URL
|
26
29
|
# hierarchy.
|
27
30
|
#
|
28
31
|
# The following example shows the Nginx configuration required to create
|
29
|
-
# a private "/files/" area, enable
|
30
|
-
#
|
32
|
+
# a private "/files/" area, enable x-accel-redirect, and pass the special
|
33
|
+
# x-sendfile-type and x-accel-mapping headers to the backend:
|
31
34
|
#
|
32
35
|
# location ~ /files/(.*) {
|
33
36
|
# internal;
|
@@ -41,24 +44,24 @@ module Rack
|
|
41
44
|
# proxy_set_header X-Real-IP $remote_addr;
|
42
45
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
43
46
|
#
|
44
|
-
# proxy_set_header
|
45
|
-
# proxy_set_header
|
47
|
+
# proxy_set_header x-sendfile-type x-accel-redirect;
|
48
|
+
# proxy_set_header x-accel-mapping /var/www/=/files/;
|
46
49
|
#
|
47
50
|
# proxy_pass http://127.0.0.1:8080/;
|
48
51
|
# }
|
49
52
|
#
|
50
|
-
# Note that the
|
51
|
-
# The
|
53
|
+
# Note that the x-sendfile-type header must be set exactly as shown above.
|
54
|
+
# The x-accel-mapping header should specify the location on the file system,
|
52
55
|
# followed by an equals sign (=), followed name of the private URL pattern
|
53
56
|
# that it maps to. The middleware performs a simple substitution on the
|
54
57
|
# resulting path.
|
55
58
|
#
|
56
|
-
# See Also:
|
59
|
+
# See Also: https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile
|
57
60
|
#
|
58
61
|
# === lighttpd
|
59
62
|
#
|
60
|
-
# Lighttpd has supported some variation of the
|
61
|
-
# time, although only recent version support
|
63
|
+
# Lighttpd has supported some variation of the x-sendfile header for some
|
64
|
+
# time, although only recent version support x-sendfile in a reverse proxy
|
62
65
|
# configuration.
|
63
66
|
#
|
64
67
|
# $HTTP["host"] == "example.com" {
|
@@ -72,7 +75,7 @@ module Rack
|
|
72
75
|
#
|
73
76
|
# proxy-core.allow-x-sendfile = "enable"
|
74
77
|
# proxy-core.rewrite-request = (
|
75
|
-
# "
|
78
|
+
# "x-sendfile-type" => (".*" => "x-sendfile")
|
76
79
|
# )
|
77
80
|
# }
|
78
81
|
#
|
@@ -80,26 +83,26 @@ module Rack
|
|
80
83
|
#
|
81
84
|
# === Apache
|
82
85
|
#
|
83
|
-
#
|
86
|
+
# x-sendfile is supported under Apache 2.x using a separate module:
|
84
87
|
#
|
85
88
|
# https://tn123.org/mod_xsendfile/
|
86
89
|
#
|
87
90
|
# Once the module is compiled and installed, you can enable it using
|
88
91
|
# XSendFile config directive:
|
89
92
|
#
|
90
|
-
# RequestHeader Set
|
93
|
+
# RequestHeader Set x-sendfile-type x-sendfile
|
91
94
|
# ProxyPassReverse / http://localhost:8001/
|
92
95
|
# XSendFile on
|
93
96
|
#
|
94
97
|
# === Mapping parameter
|
95
98
|
#
|
96
99
|
# The third parameter allows for an overriding extension of the
|
97
|
-
#
|
100
|
+
# x-accel-mapping header. Mappings should be provided in tuples of internal to
|
98
101
|
# external. The internal values may contain regular expression syntax, they
|
99
102
|
# will be matched with case indifference.
|
100
103
|
|
101
104
|
class Sendfile
|
102
|
-
def initialize(app, variation=nil, mappings=[])
|
105
|
+
def initialize(app, variation = nil, mappings = [])
|
103
106
|
@app = app
|
104
107
|
@variation = variation
|
105
108
|
@mappings = mappings.map do |internal, external|
|
@@ -108,27 +111,29 @@ module Rack
|
|
108
111
|
end
|
109
112
|
|
110
113
|
def call(env)
|
111
|
-
status, headers, body = @app.call(env)
|
114
|
+
status, headers, body = response = @app.call(env)
|
115
|
+
|
112
116
|
if body.respond_to?(:to_path)
|
113
117
|
case type = variation(env)
|
114
|
-
when
|
118
|
+
when /x-accel-redirect/i
|
115
119
|
path = ::File.expand_path(body.to_path)
|
116
120
|
if url = map_accel_path(env, path)
|
117
121
|
headers[CONTENT_LENGTH] = '0'
|
118
|
-
|
122
|
+
# '?' must be percent-encoded because it is not query string but a part of path
|
123
|
+
headers[type.downcase] = ::Rack::Utils.escape_path(url).gsub('?', '%3F')
|
119
124
|
obody = body
|
120
|
-
|
125
|
+
response[2] = Rack::BodyProxy.new([]) do
|
121
126
|
obody.close if obody.respond_to?(:close)
|
122
127
|
end
|
123
128
|
else
|
124
|
-
env[RACK_ERRORS].puts "
|
129
|
+
env[RACK_ERRORS].puts "x-accel-mapping header missing"
|
125
130
|
end
|
126
|
-
when
|
131
|
+
when /x-sendfile|x-lighttpd-send-file/i
|
127
132
|
path = ::File.expand_path(body.to_path)
|
128
133
|
headers[CONTENT_LENGTH] = '0'
|
129
|
-
headers[type] = path
|
134
|
+
headers[type.downcase] = path
|
130
135
|
obody = body
|
131
|
-
|
136
|
+
response[2] = Rack::BodyProxy.new([]) do
|
132
137
|
obody.close if obody.respond_to?(:close)
|
133
138
|
end
|
134
139
|
when '', nil
|
@@ -136,7 +141,7 @@ module Rack
|
|
136
141
|
env[RACK_ERRORS].puts "Unknown x-sendfile variation: '#{type}'.\n"
|
137
142
|
end
|
138
143
|
end
|
139
|
-
|
144
|
+
response
|
140
145
|
end
|
141
146
|
|
142
147
|
private
|
@@ -147,11 +152,15 @@ module Rack
|
|
147
152
|
end
|
148
153
|
|
149
154
|
def map_accel_path(env, path)
|
150
|
-
if mapping = @mappings.find { |internal,_| internal =~ path }
|
155
|
+
if mapping = @mappings.find { |internal, _| internal =~ path }
|
151
156
|
path.sub(*mapping)
|
152
157
|
elsif mapping = env['HTTP_X_ACCEL_MAPPING']
|
153
|
-
|
154
|
-
|
158
|
+
mapping.split(',').map(&:strip).each do |m|
|
159
|
+
internal, external = m.split('=', 2).map(&:strip)
|
160
|
+
new_path = path.sub(/^#{internal}/i, external)
|
161
|
+
return new_path unless path == new_path
|
162
|
+
end
|
163
|
+
path
|
155
164
|
end
|
156
165
|
end
|
157
166
|
end
|
data/lib/rack/show_exceptions.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ostruct'
|
2
4
|
require 'erb'
|
3
|
-
|
4
|
-
|
5
|
+
|
6
|
+
require_relative 'constants'
|
7
|
+
require_relative 'utils'
|
8
|
+
require_relative 'request'
|
5
9
|
|
6
10
|
module Rack
|
7
11
|
# Rack::ShowExceptions catches all exceptions raised from the app it
|
@@ -55,7 +59,12 @@ module Rack
|
|
55
59
|
private :accepts_html?
|
56
60
|
|
57
61
|
def dump_exception(exception)
|
58
|
-
|
62
|
+
if exception.respond_to?(:detailed_message)
|
63
|
+
message = exception.detailed_message(highlight: false)
|
64
|
+
else
|
65
|
+
message = exception.message
|
66
|
+
end
|
67
|
+
string = "#{exception.class}: #{message}\n".dup
|
59
68
|
string << exception.backtrace.map { |l| "\t#{l}" }.join("\n")
|
60
69
|
string
|
61
70
|
end
|
@@ -63,12 +72,12 @@ module Rack
|
|
63
72
|
def pretty(env, exception)
|
64
73
|
req = Rack::Request.new(env)
|
65
74
|
|
66
|
-
# This double assignment is to prevent an "unused variable" warning
|
67
|
-
#
|
75
|
+
# This double assignment is to prevent an "unused variable" warning.
|
76
|
+
# Yes, it is dumb, but I don't like Ruby yelling at me.
|
68
77
|
path = path = (req.script_name + req.path_info).squeeze("/")
|
69
78
|
|
70
|
-
# This double assignment is to prevent an "unused variable" warning
|
71
|
-
#
|
79
|
+
# This double assignment is to prevent an "unused variable" warning.
|
80
|
+
# Yes, it is dumb, but I don't like Ruby yelling at me.
|
72
81
|
frames = frames = exception.backtrace.map { |line|
|
73
82
|
frame = OpenStruct.new
|
74
83
|
if line =~ /(.*?):(\d+)(:in `(.*)')?/
|
@@ -77,13 +86,13 @@ module Rack
|
|
77
86
|
frame.function = $4
|
78
87
|
|
79
88
|
begin
|
80
|
-
lineno = frame.lineno-1
|
89
|
+
lineno = frame.lineno - 1
|
81
90
|
lines = ::File.readlines(frame.filename)
|
82
|
-
frame.pre_context_lineno = [lineno-CONTEXT, 0].max
|
91
|
+
frame.pre_context_lineno = [lineno - CONTEXT, 0].max
|
83
92
|
frame.pre_context = lines[frame.pre_context_lineno...lineno]
|
84
93
|
frame.context_line = lines[lineno].chomp
|
85
|
-
frame.post_context_lineno = [lineno+CONTEXT, lines.size].min
|
86
|
-
frame.post_context = lines[lineno+1..frame.post_context_lineno]
|
94
|
+
frame.post_context_lineno = [lineno + CONTEXT, lines.size].min
|
95
|
+
frame.post_context = lines[lineno + 1..frame.post_context_lineno]
|
87
96
|
rescue
|
88
97
|
end
|
89
98
|
|
@@ -93,7 +102,11 @@ module Rack
|
|
93
102
|
end
|
94
103
|
}.compact
|
95
104
|
|
96
|
-
|
105
|
+
template.result(binding)
|
106
|
+
end
|
107
|
+
|
108
|
+
def template
|
109
|
+
TEMPLATE
|
97
110
|
end
|
98
111
|
|
99
112
|
def h(obj) # :nodoc:
|
@@ -107,8 +120,8 @@ module Rack
|
|
107
120
|
|
108
121
|
# :stopdoc:
|
109
122
|
|
110
|
-
# adapted from Django <djangoproject.com>
|
111
|
-
# Copyright (c)
|
123
|
+
# adapted from Django <www.djangoproject.com>
|
124
|
+
# Copyright (c) Django Software Foundation and individual contributors.
|
112
125
|
# Used under the modified BSD license:
|
113
126
|
# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
|
114
127
|
TEMPLATE = ERB.new(<<-'HTML'.gsub(/^ /, ''))
|
@@ -155,7 +168,7 @@ module Rack
|
|
155
168
|
div.commands { margin-left: 40px; }
|
156
169
|
div.commands a { color:black; text-decoration:none; }
|
157
170
|
#summary { background: #ffc; }
|
158
|
-
#summary h2 { font-weight: normal; color: #666; }
|
171
|
+
#summary h2 { font-family: monospace; font-weight: normal; color: #666; white-space: pre-wrap; }
|
159
172
|
#summary ul#quicklinks { list-style-type: none; margin-bottom: 2em; }
|
160
173
|
#summary ul#quicklinks li { float: left; padding: 0 1em; }
|
161
174
|
#summary ul#quicklinks>li+li { border-left: 1px #666 solid; }
|
@@ -223,7 +236,11 @@ module Rack
|
|
223
236
|
|
224
237
|
<div id="summary">
|
225
238
|
<h1><%=h exception.class %> at <%=h path %></h1>
|
239
|
+
<% if exception.respond_to?(:detailed_message) %>
|
240
|
+
<h2><%=h exception.detailed_message(highlight: false) %></h2>
|
241
|
+
<% else %>
|
226
242
|
<h2><%=h exception.message %></h2>
|
243
|
+
<% end %>
|
227
244
|
<table><tr>
|
228
245
|
<th>Ruby</th>
|
229
246
|
<td>
|
@@ -307,7 +324,7 @@ module Rack
|
|
307
324
|
<% end %>
|
308
325
|
|
309
326
|
<h3 id="post-info">POST</h3>
|
310
|
-
<% if req.POST and not req.POST.empty? %>
|
327
|
+
<% if ((req.POST and not req.POST.empty?) rescue (no_post_data = "Invalid POST data"; nil)) %>
|
311
328
|
<table class="req">
|
312
329
|
<thead>
|
313
330
|
<tr>
|
@@ -325,7 +342,7 @@ module Rack
|
|
325
342
|
</tbody>
|
326
343
|
</table>
|
327
344
|
<% else %>
|
328
|
-
<p
|
345
|
+
<p><%= no_post_data || "No POST data" %>.</p>
|
329
346
|
<% end %>
|
330
347
|
|
331
348
|
|
@@ -363,7 +380,7 @@ module Rack
|
|
363
380
|
<% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
364
381
|
<tr>
|
365
382
|
<td><%=h key %></td>
|
366
|
-
<td class="code"><div><%=h val %></div></td>
|
383
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
367
384
|
</tr>
|
368
385
|
<% } %>
|
369
386
|
</tbody>
|
data/lib/rack/show_status.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'erb'
|
2
|
-
|
3
|
-
|
4
|
+
|
5
|
+
require_relative 'constants'
|
6
|
+
require_relative 'utils'
|
7
|
+
require_relative 'request'
|
8
|
+
require_relative 'body_proxy'
|
4
9
|
|
5
10
|
module Rack
|
6
11
|
# Rack::ShowStatus catches all empty responses and replaces them
|
@@ -17,28 +22,33 @@ module Rack
|
|
17
22
|
end
|
18
23
|
|
19
24
|
def call(env)
|
20
|
-
status, headers, body = @app.call(env)
|
21
|
-
headers = Utils::HeaderHash.new(headers)
|
25
|
+
status, headers, body = response = @app.call(env)
|
22
26
|
empty = headers[CONTENT_LENGTH].to_i <= 0
|
23
27
|
|
24
28
|
# client or server error, or explicit message
|
25
29
|
if (status.to_i >= 400 && empty) || env[RACK_SHOWSTATUS_DETAIL]
|
26
|
-
# This double assignment is to prevent an "unused variable" warning
|
27
|
-
#
|
30
|
+
# This double assignment is to prevent an "unused variable" warning.
|
31
|
+
# Yes, it is dumb, but I don't like Ruby yelling at me.
|
28
32
|
req = req = Rack::Request.new(env)
|
29
33
|
|
30
34
|
message = Rack::Utils::HTTP_STATUS_CODES[status.to_i] || status.to_s
|
31
35
|
|
32
|
-
# This double assignment is to prevent an "unused variable" warning
|
33
|
-
#
|
36
|
+
# This double assignment is to prevent an "unused variable" warning.
|
37
|
+
# Yes, it is dumb, but I don't like Ruby yelling at me.
|
34
38
|
detail = detail = env[RACK_SHOWSTATUS_DETAIL] || message
|
35
39
|
|
36
|
-
|
37
|
-
size =
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
html = @template.result(binding)
|
41
|
+
size = html.bytesize
|
42
|
+
|
43
|
+
response[2] = Rack::BodyProxy.new([html]) do
|
44
|
+
body.close if body.respond_to?(:close)
|
45
|
+
end
|
46
|
+
|
47
|
+
headers[CONTENT_TYPE] = "text/html"
|
48
|
+
headers[CONTENT_LENGTH] = size.to_s
|
41
49
|
end
|
50
|
+
|
51
|
+
response
|
42
52
|
end
|
43
53
|
|
44
54
|
def h(obj) # :nodoc:
|
@@ -52,8 +62,8 @@ module Rack
|
|
52
62
|
|
53
63
|
# :stopdoc:
|
54
64
|
|
55
|
-
# adapted from Django <djangoproject.com>
|
56
|
-
# Copyright (c)
|
65
|
+
# adapted from Django <www.djangoproject.com>
|
66
|
+
# Copyright (c) Django Software Foundation and individual contributors.
|
57
67
|
# Used under the modified BSD license:
|
58
68
|
# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
|
59
69
|
TEMPLATE = <<'HTML'
|
data/lib/rack/static.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'constants'
|
4
|
+
require_relative 'files'
|
5
|
+
require_relative 'mime'
|
3
6
|
|
4
7
|
module Rack
|
5
8
|
|
6
9
|
# The Rack::Static middleware intercepts requests for static files
|
7
10
|
# (javascript files, images, stylesheets, etc) based on the url prefixes or
|
8
|
-
# route mappings passed in the options, and serves them using a Rack::
|
11
|
+
# route mappings passed in the options, and serves them using a Rack::Files
|
9
12
|
# object. This allows a Rack stack to serve both static and dynamic content.
|
10
13
|
#
|
11
14
|
# Examples:
|
@@ -15,6 +18,11 @@ module Rack
|
|
15
18
|
#
|
16
19
|
# use Rack::Static, :urls => ["/media"]
|
17
20
|
#
|
21
|
+
# Same as previous, but instead of returning 404 for missing files under
|
22
|
+
# /media, call the next middleware:
|
23
|
+
#
|
24
|
+
# use Rack::Static, :urls => ["/media"], :cascade => true
|
25
|
+
#
|
18
26
|
# Serve all requests beginning with /css or /images from the folder "public"
|
19
27
|
# in the current directory (ie public/css/* and public/images/*):
|
20
28
|
#
|
@@ -74,32 +82,32 @@ module Rack
|
|
74
82
|
# :header_rules => [
|
75
83
|
# # Cache all static files in public caches (e.g. Rack::Cache)
|
76
84
|
# # as well as in the browser
|
77
|
-
# [:all, {'
|
85
|
+
# [:all, {'cache-control' => 'public, max-age=31536000'}],
|
78
86
|
#
|
79
87
|
# # Provide web fonts with cross-origin access-control-headers
|
80
88
|
# # Firefox requires this when serving assets using a Content Delivery Network
|
81
|
-
# [:fonts, {'
|
89
|
+
# [:fonts, {'access-control-allow-origin' => '*'}]
|
82
90
|
# ]
|
83
91
|
#
|
84
92
|
class Static
|
85
|
-
|
86
|
-
def initialize(app, options={})
|
93
|
+
def initialize(app, options = {})
|
87
94
|
@app = app
|
88
95
|
@urls = options[:urls] || ["/favicon.ico"]
|
89
96
|
@index = options[:index]
|
90
97
|
@gzip = options[:gzip]
|
98
|
+
@cascade = options[:cascade]
|
91
99
|
root = options[:root] || Dir.pwd
|
92
100
|
|
93
101
|
# HTTP Headers
|
94
102
|
@header_rules = options[:header_rules] || []
|
95
103
|
# Allow for legacy :cache_control option while prioritizing global header_rules setting
|
96
|
-
@header_rules.unshift([:all, {CACHE_CONTROL => options[:cache_control]}]) if options[:cache_control]
|
104
|
+
@header_rules.unshift([:all, { CACHE_CONTROL => options[:cache_control] }]) if options[:cache_control]
|
97
105
|
|
98
|
-
@file_server = Rack::
|
106
|
+
@file_server = Rack::Files.new(root)
|
99
107
|
end
|
100
108
|
|
101
109
|
def add_index_root?(path)
|
102
|
-
@index && path
|
110
|
+
@index && route_file(path) && path.end_with?('/')
|
103
111
|
end
|
104
112
|
|
105
113
|
def overwrite_file_path(path)
|
@@ -120,7 +128,7 @@ module Rack
|
|
120
128
|
if can_serve(path)
|
121
129
|
if overwrite_file_path(path)
|
122
130
|
env[PATH_INFO] = (add_index_root?(path) ? path + @index : @urls[path])
|
123
|
-
elsif @gzip && env['HTTP_ACCEPT_ENCODING']
|
131
|
+
elsif @gzip && env['HTTP_ACCEPT_ENCODING'] && /\bgzip\b/.match?(env['HTTP_ACCEPT_ENCODING'])
|
124
132
|
path = env[PATH_INFO]
|
125
133
|
env[PATH_INFO] += '.gz'
|
126
134
|
response = @file_server.call(env)
|
@@ -128,17 +136,21 @@ module Rack
|
|
128
136
|
|
129
137
|
if response[0] == 404
|
130
138
|
response = nil
|
139
|
+
elsif response[0] == 304
|
140
|
+
# Do nothing, leave headers as is
|
131
141
|
else
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
response[1]['Content-Encoding'] = 'gzip'
|
142
|
+
response[1][CONTENT_TYPE] = Mime.mime_type(::File.extname(path), 'text/plain')
|
143
|
+
response[1]['content-encoding'] = 'gzip'
|
136
144
|
end
|
137
145
|
end
|
138
146
|
|
139
147
|
path = env[PATH_INFO]
|
140
148
|
response ||= @file_server.call(env)
|
141
149
|
|
150
|
+
if @cascade && response[0] == 404
|
151
|
+
return @app.call(env)
|
152
|
+
end
|
153
|
+
|
142
154
|
headers = response[1]
|
143
155
|
applicable_rules(path).each do |rule, new_headers|
|
144
156
|
new_headers.each { |field, content| headers[field] = content }
|
@@ -157,14 +169,14 @@ module Rack
|
|
157
169
|
when :all
|
158
170
|
true
|
159
171
|
when :fonts
|
160
|
-
|
172
|
+
/\.(?:ttf|otf|eot|woff2|woff|svg)\z/.match?(path)
|
161
173
|
when String
|
162
174
|
path = ::Rack::Utils.unescape(path)
|
163
175
|
path.start_with?(rule) || path.start_with?('/' + rule)
|
164
176
|
when Array
|
165
|
-
|
177
|
+
/\.(#{rule.join('|')})\z/.match?(path)
|
166
178
|
when Regexp
|
167
|
-
path
|
179
|
+
rule.match?(path)
|
168
180
|
else
|
169
181
|
false
|
170
182
|
end
|
data/lib/rack/tempfile_reaper.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'constants'
|
4
|
+
require_relative 'body_proxy'
|
2
5
|
|
3
6
|
module Rack
|
4
7
|
|
@@ -12,11 +15,19 @@ module Rack
|
|
12
15
|
|
13
16
|
def call(env)
|
14
17
|
env[RACK_TEMPFILES] ||= []
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
|
19
|
+
begin
|
20
|
+
_, _, body = response = @app.call(env)
|
21
|
+
rescue Exception
|
22
|
+
env[RACK_TEMPFILES]&.each(&:close!)
|
23
|
+
raise
|
18
24
|
end
|
19
|
-
|
25
|
+
|
26
|
+
response[2] = BodyProxy.new(body) do
|
27
|
+
env[RACK_TEMPFILES]&.each(&:close!)
|
28
|
+
end
|
29
|
+
|
30
|
+
response
|
20
31
|
end
|
21
32
|
end
|
22
33
|
end
|
data/lib/rack/urlmap.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require_relative 'constants'
|
6
|
+
|
1
7
|
module Rack
|
2
8
|
# Rack::URLMap takes a hash mapping urls or paths to apps, and
|
3
9
|
# dispatches accordingly. Support for HTTP/1.1 host names exists if
|
@@ -12,17 +18,16 @@ module Rack
|
|
12
18
|
# first, since they are most specific.
|
13
19
|
|
14
20
|
class URLMap
|
15
|
-
NEGATIVE_INFINITY = -1.0 / 0.0
|
16
|
-
INFINITY = 1.0 / 0.0
|
17
|
-
|
18
21
|
def initialize(map = {})
|
19
22
|
remap(map)
|
20
23
|
end
|
21
24
|
|
22
25
|
def remap(map)
|
26
|
+
@known_hosts = Set[]
|
23
27
|
@mapping = map.map { |location, app|
|
24
28
|
if location =~ %r{\Ahttps?://(.*?)(/.*)}
|
25
29
|
host, location = $1, $2
|
30
|
+
@known_hosts << host
|
26
31
|
else
|
27
32
|
host = nil
|
28
33
|
end
|
@@ -36,7 +41,7 @@ module Rack
|
|
36
41
|
|
37
42
|
[host, location, match, app]
|
38
43
|
}.sort_by do |(host, location, _, _)|
|
39
|
-
[host ? -host.size : INFINITY, -location.size]
|
44
|
+
[host ? -host.size : Float::INFINITY, -location.size]
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
@@ -50,10 +55,13 @@ module Rack
|
|
50
55
|
is_same_server = casecmp?(http_host, server_name) ||
|
51
56
|
casecmp?(http_host, "#{server_name}:#{server_port}")
|
52
57
|
|
58
|
+
is_host_known = @known_hosts.include? http_host
|
59
|
+
|
53
60
|
@mapping.each do |host, location, match, app|
|
54
61
|
unless casecmp?(http_host, host) \
|
55
62
|
|| casecmp?(server_name, host) \
|
56
|
-
|| (!host && is_same_server)
|
63
|
+
|| (!host && is_same_server) \
|
64
|
+
|| (!host && !is_host_known) # If we don't have a matching host, default to the first without a specified host
|
57
65
|
next
|
58
66
|
end
|
59
67
|
|
@@ -68,7 +76,7 @@ module Rack
|
|
68
76
|
return app.call(env)
|
69
77
|
end
|
70
78
|
|
71
|
-
[404, {CONTENT_TYPE => "text/plain", "
|
79
|
+
[404, { CONTENT_TYPE => "text/plain", "x-cascade" => "pass" }, ["Not Found: #{path}"]]
|
72
80
|
|
73
81
|
ensure
|
74
82
|
env[PATH_INFO] = path
|