rack 2.2.9 → 3.1.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +330 -88
- data/CONTRIBUTING.md +63 -55
- data/MIT-LICENSE +1 -1
- data/README.md +328 -0
- data/SPEC.rdoc +204 -131
- data/lib/rack/auth/abstract/handler.rb +3 -1
- data/lib/rack/auth/abstract/request.rb +3 -1
- data/lib/rack/auth/basic.rb +1 -4
- data/lib/rack/bad_request.rb +8 -0
- data/lib/rack/body_proxy.rb +21 -3
- data/lib/rack/builder.rb +102 -69
- data/lib/rack/cascade.rb +2 -3
- data/lib/rack/common_logger.rb +23 -18
- data/lib/rack/conditional_get.rb +18 -15
- data/lib/rack/constants.rb +67 -0
- data/lib/rack/content_length.rb +12 -16
- data/lib/rack/content_type.rb +8 -5
- data/lib/rack/deflater.rb +40 -26
- data/lib/rack/directory.rb +9 -3
- data/lib/rack/etag.rb +14 -23
- data/lib/rack/events.rb +4 -0
- data/lib/rack/files.rb +15 -17
- data/lib/rack/head.rb +9 -8
- data/lib/rack/headers.rb +238 -0
- data/lib/rack/lint.rb +840 -644
- data/lib/rack/lock.rb +2 -5
- data/lib/rack/logger.rb +3 -0
- data/lib/rack/method_override.rb +5 -1
- data/lib/rack/mime.rb +14 -5
- data/lib/rack/mock.rb +1 -271
- data/lib/rack/mock_request.rb +161 -0
- data/lib/rack/mock_response.rb +124 -0
- data/lib/rack/multipart/generator.rb +7 -5
- data/lib/rack/multipart/parser.rb +213 -95
- data/lib/rack/multipart/uploaded_file.rb +4 -0
- data/lib/rack/multipart.rb +53 -40
- data/lib/rack/null_logger.rb +9 -0
- data/lib/rack/query_parser.rb +81 -102
- data/lib/rack/recursive.rb +2 -0
- data/lib/rack/reloader.rb +0 -2
- data/lib/rack/request.rb +260 -123
- data/lib/rack/response.rb +151 -66
- data/lib/rack/rewindable_input.rb +24 -5
- data/lib/rack/runtime.rb +7 -6
- data/lib/rack/sendfile.rb +30 -25
- data/lib/rack/show_exceptions.rb +21 -4
- data/lib/rack/show_status.rb +17 -7
- data/lib/rack/static.rb +8 -8
- data/lib/rack/tempfile_reaper.rb +15 -4
- data/lib/rack/urlmap.rb +3 -1
- data/lib/rack/utils.rb +232 -233
- data/lib/rack/version.rb +1 -9
- data/lib/rack.rb +13 -89
- metadata +15 -41
- data/README.rdoc +0 -320
- data/Rakefile +0 -130
- data/bin/rackup +0 -5
- 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 -6
- data/example/protectedlobster.rb +0 -16
- data/example/protectedlobster.ru +0 -10
- data/lib/rack/auth/digest/md5.rb +0 -131
- data/lib/rack/auth/digest/nonce.rb +0 -54
- data/lib/rack/auth/digest/params.rb +0 -54
- data/lib/rack/auth/digest/request.rb +0 -43
- data/lib/rack/chunked.rb +0 -117
- data/lib/rack/core_ext/regexp.rb +0 -14
- data/lib/rack/file.rb +0 -7
- data/lib/rack/handler/cgi.rb +0 -59
- data/lib/rack/handler/fastcgi.rb +0 -100
- data/lib/rack/handler/lsws.rb +0 -61
- data/lib/rack/handler/scgi.rb +0 -71
- data/lib/rack/handler/thin.rb +0 -36
- data/lib/rack/handler/webrick.rb +0 -129
- data/lib/rack/handler.rb +0 -104
- data/lib/rack/lobster.rb +0 -70
- data/lib/rack/server.rb +0 -466
- data/lib/rack/session/abstract/id.rb +0 -523
- data/lib/rack/session/cookie.rb +0 -204
- data/lib/rack/session/memcache.rb +0 -10
- data/lib/rack/session/pool.rb +0 -85
- data/rack.gemspec +0 -46
data/SPEC.rdoc
CHANGED
@@ -1,23 +1,27 @@
|
|
1
|
-
This specification aims to formalize the Rack protocol.
|
1
|
+
This specification aims to formalize the Rack protocol. You
|
2
2
|
can (and should) use Rack::Lint to enforce it.
|
3
3
|
|
4
4
|
When you develop middleware, be sure to add a Lint before and
|
5
5
|
after to catch all mistakes.
|
6
|
+
|
6
7
|
= Rack applications
|
8
|
+
|
7
9
|
A Rack application is a Ruby object (not a class) that
|
8
10
|
responds to +call+.
|
9
11
|
It takes exactly one argument, the *environment*
|
10
|
-
and returns
|
12
|
+
and returns a non-frozen Array of exactly three values:
|
11
13
|
The *status*,
|
12
14
|
the *headers*,
|
13
15
|
and the *body*.
|
16
|
+
|
14
17
|
== The Environment
|
18
|
+
|
15
19
|
The environment must be an unfrozen instance of Hash that includes
|
16
|
-
CGI-like headers.
|
20
|
+
CGI-like headers. The Rack application is free to modify the
|
17
21
|
environment.
|
18
22
|
|
19
23
|
The environment is required to include these variables
|
20
|
-
(adopted from
|
24
|
+
(adopted from {PEP 333}[https://peps.python.org/pep-0333/]), except when they'd be empty, but see
|
21
25
|
below.
|
22
26
|
<tt>REQUEST_METHOD</tt>:: The HTTP request method, such as
|
23
27
|
"GET" or "POST". This cannot ever
|
@@ -54,6 +58,8 @@ below.
|
|
54
58
|
<tt>SERVER_PORT</tt>:: An optional +Integer+ which is the port the
|
55
59
|
server is running on. Should be specified if
|
56
60
|
the server is running on a non-standard port.
|
61
|
+
<tt>SERVER_PROTOCOL</tt>:: A string representing the HTTP version used
|
62
|
+
for the request.
|
57
63
|
<tt>HTTP_</tt> Variables:: Variables corresponding to the
|
58
64
|
client-supplied HTTP request
|
59
65
|
headers (i.e., variables whose
|
@@ -67,40 +73,23 @@ below.
|
|
67
73
|
for specific behavior.
|
68
74
|
In addition to this, the Rack environment must include these
|
69
75
|
Rack-specific variables:
|
70
|
-
<tt>rack.version</tt>:: The Array representing this version of Rack
|
71
|
-
See Rack::VERSION, that corresponds to
|
72
|
-
the version of this SPEC.
|
73
76
|
<tt>rack.url_scheme</tt>:: +http+ or +https+, depending on the
|
74
77
|
request URL.
|
75
78
|
<tt>rack.input</tt>:: See below, the input stream.
|
76
79
|
<tt>rack.errors</tt>:: See below, the error stream.
|
77
|
-
<tt>rack.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
time during the life of its containing
|
87
|
-
process. Normally, this will only be true
|
88
|
-
for a server based on CGI
|
89
|
-
(or something similar).
|
90
|
-
<tt>rack.hijack?</tt>:: present and true if the server supports
|
91
|
-
connection hijacking. See below, hijacking.
|
92
|
-
<tt>rack.hijack</tt>:: an object responding to #call that must be
|
93
|
-
called at least once before using
|
94
|
-
rack.hijack_io.
|
95
|
-
It is recommended #call return rack.hijack_io
|
96
|
-
as well as setting it in env if necessary.
|
97
|
-
<tt>rack.hijack_io</tt>:: if rack.hijack? is true, and rack.hijack
|
98
|
-
has received #call, this will contain
|
99
|
-
an object resembling an IO. See hijacking.
|
80
|
+
<tt>rack.hijack?</tt>:: See below, if present and true, indicates
|
81
|
+
that the server supports partial hijacking.
|
82
|
+
<tt>rack.hijack</tt>:: See below, if present, an object responding
|
83
|
+
to +call+ that is used to perform a full
|
84
|
+
hijack.
|
85
|
+
<tt>rack.protocol</tt>:: An optional +Array+ of +String+, containing
|
86
|
+
the protocols advertised by the client in
|
87
|
+
the +upgrade+ header (HTTP/1) or the
|
88
|
+
+:protocol+ pseudo-header (HTTP/2).
|
100
89
|
Additional environment specifications have approved to
|
101
|
-
standardized middleware APIs.
|
90
|
+
standardized middleware APIs. None of these are required to
|
102
91
|
be implemented by the server.
|
103
|
-
<tt>rack.session</tt>:: A hash
|
92
|
+
<tt>rack.session</tt>:: A hash-like interface for storing
|
104
93
|
request session data.
|
105
94
|
The store must implement:
|
106
95
|
store(key, value) (aliased as []=);
|
@@ -126,6 +115,7 @@ accepted specifications and must not be used otherwise.
|
|
126
115
|
The <tt>SERVER_PORT</tt> must be an Integer if set.
|
127
116
|
The <tt>SERVER_NAME</tt> must be a valid authority as defined by RFC7540.
|
128
117
|
The <tt>HTTP_HOST</tt> must be a valid authority as defined by RFC7540.
|
118
|
+
The <tt>SERVER_PROTOCOL</tt> must match the regexp <tt>HTTP/\d(\.\d)?</tt>.
|
129
119
|
The environment must not contain the keys
|
130
120
|
<tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
|
131
121
|
(use the versions without <tt>HTTP_</tt>).
|
@@ -133,29 +123,40 @@ The CGI keys (named without a period) must have String values.
|
|
133
123
|
If the string values for CGI keys contain non-ASCII characters,
|
134
124
|
they should use ASCII-8BIT encoding.
|
135
125
|
There are the following restrictions:
|
136
|
-
* <tt>rack.version</tt> must be an array of Integers.
|
137
126
|
* <tt>rack.url_scheme</tt> must either be +http+ or +https+.
|
138
|
-
* There
|
127
|
+
* There may be a valid input stream in <tt>rack.input</tt>.
|
139
128
|
* There must be a valid error stream in <tt>rack.errors</tt>.
|
140
|
-
* There may be a valid hijack
|
129
|
+
* There may be a valid hijack callback in <tt>rack.hijack</tt>
|
130
|
+
* There may be a valid early hints callback in <tt>rack.early_hints</tt>
|
141
131
|
* The <tt>REQUEST_METHOD</tt> must be a valid token.
|
142
132
|
* The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
|
143
|
-
* The <tt>PATH_INFO</tt>, if
|
133
|
+
* The <tt>PATH_INFO</tt>, if provided, must be a valid request target or an empty string.
|
134
|
+
* Only <tt>OPTIONS</tt> requests may have <tt>PATH_INFO</tt> set to <tt>*</tt> (asterisk-form).
|
135
|
+
* Only <tt>CONNECT</tt> requests may have <tt>PATH_INFO</tt> set to an authority (authority-form). Note that in HTTP/2+, the authority-form is not a valid request target.
|
136
|
+
* <tt>CONNECT</tt> and <tt>OPTIONS</tt> requests must not have <tt>PATH_INFO</tt> set to a URI (absolute-form).
|
137
|
+
* Otherwise, <tt>PATH_INFO</tt> must start with a <tt>/</tt> and must not include a fragment part starting with '#' (origin-form).
|
144
138
|
* The <tt>CONTENT_LENGTH</tt>, if given, must consist of digits only.
|
145
139
|
* One of <tt>SCRIPT_NAME</tt> or <tt>PATH_INFO</tt> must be
|
146
|
-
set.
|
140
|
+
set. <tt>PATH_INFO</tt> should be <tt>/</tt> if
|
147
141
|
<tt>SCRIPT_NAME</tt> is empty.
|
148
142
|
<tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
|
143
|
+
<tt>rack.response_finished</tt>:: An array of callables run by the server after the response has been
|
144
|
+
processed. This would typically be invoked after sending the response to the client, but it could also be
|
145
|
+
invoked if an error occurs while generating the response or sending the response; in that case, the error
|
146
|
+
argument will be a subclass of +Exception+.
|
147
|
+
The callables are invoked with +env, status, headers, error+ arguments and should not raise any
|
148
|
+
exceptions. They should be invoked in reverse order of registration.
|
149
|
+
|
149
150
|
=== The Input Stream
|
150
151
|
|
151
152
|
The input stream is an IO-like object which contains the raw HTTP
|
152
153
|
POST data.
|
153
154
|
When applicable, its external encoding must be "ASCII-8BIT" and it
|
154
|
-
must be opened in binary mode
|
155
|
-
The input stream must respond to +gets+, +each+,
|
155
|
+
must be opened in binary mode.
|
156
|
+
The input stream must respond to +gets+, +each+, and +read+.
|
156
157
|
* +gets+ must be called without arguments and return a string,
|
157
158
|
or +nil+ on EOF.
|
158
|
-
* +read+ behaves like IO#read
|
159
|
+
* +read+ behaves like <tt>IO#read</tt>.
|
159
160
|
Its signature is <tt>read([length, [buffer]])</tt>.
|
160
161
|
|
161
162
|
If given, +length+ must be a non-negative Integer (>= 0) or +nil+,
|
@@ -173,120 +174,192 @@ The input stream must respond to +gets+, +each+, +read+ and +rewind+.
|
|
173
174
|
If +buffer+ is given, then the read data will be placed
|
174
175
|
into +buffer+ instead of a newly created String object.
|
175
176
|
* +each+ must be called without arguments and only yield Strings.
|
176
|
-
* +
|
177
|
-
|
178
|
-
|
179
|
-
developers must buffer the input data into some rewindable object
|
180
|
-
if the underlying input stream is not rewindable.
|
181
|
-
* +close+ must never be called on the input stream.
|
177
|
+
* +close+ can be called on the input stream to indicate that
|
178
|
+
any remaining input is not needed.
|
179
|
+
|
182
180
|
=== The Error Stream
|
181
|
+
|
183
182
|
The error stream must respond to +puts+, +write+ and +flush+.
|
184
183
|
* +puts+ must be called with a single argument that responds to +to_s+.
|
185
184
|
* +write+ must be called with a single argument that is a String.
|
186
185
|
* +flush+ must be called without arguments and must be called
|
187
186
|
in order to make the error appear for sure.
|
188
187
|
* +close+ must never be called on the error stream.
|
188
|
+
|
189
189
|
=== Hijacking
|
190
|
-
==== Request (before status)
|
191
|
-
If rack.hijack? is true then rack.hijack must respond to #call.
|
192
|
-
rack.hijack must return the io that will also be assigned (or is
|
193
|
-
already present, in rack.hijack_io.
|
194
190
|
|
195
|
-
|
196
|
-
|
197
|
-
|
191
|
+
The hijacking interfaces provides a means for an application to take
|
192
|
+
control of the HTTP connection. There are two distinct hijack
|
193
|
+
interfaces: full hijacking where the application takes over the raw
|
194
|
+
connection, and partial hijacking where the application takes over
|
195
|
+
just the response body stream. In both cases, the application is
|
196
|
+
responsible for closing the hijacked stream.
|
197
|
+
|
198
|
+
Full hijacking only works with HTTP/1. Partial hijacking is functionally
|
199
|
+
equivalent to streaming bodies, and is still optionally supported for
|
200
|
+
backwards compatibility with older Rack versions.
|
201
|
+
|
202
|
+
==== Full Hijack
|
203
|
+
|
204
|
+
Full hijack is used to completely take over an HTTP/1 connection. It
|
205
|
+
occurs before any headers are written and causes the request to
|
206
|
+
ignores any response generated by the application.
|
207
|
+
|
208
|
+
It is intended to be used when applications need access to raw HTTP/1
|
209
|
+
connection.
|
210
|
+
|
211
|
+
If +rack.hijack+ is present in +env+, it must respond to +call+
|
212
|
+
and return an +IO+ instance which can be used to read and write
|
213
|
+
to the underlying connection using HTTP/1 semantics and
|
214
|
+
formatting.
|
215
|
+
|
216
|
+
==== Partial Hijack
|
217
|
+
|
218
|
+
Partial hijack is used for bi-directional streaming of the request and
|
219
|
+
response body. It occurs after the status and headers are written by
|
220
|
+
the server and causes the server to ignore the Body of the response.
|
221
|
+
|
222
|
+
It is intended to be used when applications need bi-directional
|
223
|
+
streaming.
|
224
|
+
|
225
|
+
If +rack.hijack?+ is present in +env+ and truthy,
|
226
|
+
an application may set the special response header +rack.hijack+
|
227
|
+
to an object that responds to +call+,
|
228
|
+
accepting a +stream+ argument.
|
229
|
+
|
230
|
+
After the response status and headers have been sent, this hijack
|
231
|
+
callback will be invoked with a +stream+ argument which follows the
|
232
|
+
same interface as outlined in "Streaming Body". Servers must
|
233
|
+
ignore the +body+ part of the response tuple when the
|
234
|
+
+rack.hijack+ response header is present. Using an empty +Array+
|
235
|
+
instance is recommended.
|
236
|
+
|
237
|
+
The special response header +rack.hijack+ must only be set
|
238
|
+
if the request +env+ has a truthy +rack.hijack?+.
|
239
|
+
|
240
|
+
=== Early Hints
|
241
|
+
|
242
|
+
The application or any middleware may call the <tt>rack.early_hints</tt>
|
243
|
+
with an object which would be valid as the headers of a Rack response.
|
244
|
+
|
245
|
+
If <tt>rack.early_hints</tt> is present, it must respond to #call.
|
246
|
+
If <tt>rack.early_hints</tt> is called, it must be called with
|
247
|
+
valid Rack response headers.
|
198
248
|
|
199
|
-
The semantics of these IO methods must be a best effort match to
|
200
|
-
those of a normal ruby IO or Socket object, using standard
|
201
|
-
arguments and raising standard exceptions. Servers are encouraged
|
202
|
-
to simply pass on real IO objects, although it is recognized that
|
203
|
-
this approach is not directly compatible with SPDY and HTTP 2.0.
|
204
|
-
|
205
|
-
IO provided in rack.hijack_io should preference the
|
206
|
-
IO::WaitReadable and IO::WaitWritable APIs wherever supported.
|
207
|
-
|
208
|
-
There is a deliberate lack of full specification around
|
209
|
-
rack.hijack_io, as semantics will change from server to server.
|
210
|
-
Users are encouraged to utilize this API with a knowledge of their
|
211
|
-
server choice, and servers may extend the functionality of
|
212
|
-
hijack_io to provide additional features to users. The purpose of
|
213
|
-
rack.hijack is for Rack to "get out of the way", as such, Rack only
|
214
|
-
provides the minimum of specification and support.
|
215
|
-
|
216
|
-
If rack.hijack? is false, then rack.hijack should not be set.
|
217
|
-
|
218
|
-
If rack.hijack? is false, then rack.hijack_io should not be set.
|
219
|
-
==== Response (after headers)
|
220
|
-
It is also possible to hijack a response after the status and headers
|
221
|
-
have been sent.
|
222
|
-
In order to do this, an application may set the special header
|
223
|
-
<tt>rack.hijack</tt> to an object that responds to <tt>call</tt>
|
224
|
-
accepting an argument that conforms to the <tt>rack.hijack_io</tt>
|
225
|
-
protocol.
|
226
|
-
|
227
|
-
After the headers have been sent, and this hijack callback has been
|
228
|
-
called, the application is now responsible for the remaining lifecycle
|
229
|
-
of the IO. The application is also responsible for maintaining HTTP
|
230
|
-
semantics. Of specific note, in almost all cases in the current SPEC,
|
231
|
-
applications will have wanted to specify the header Connection:close in
|
232
|
-
HTTP/1.1, and not Connection:keep-alive, as there is no protocol for
|
233
|
-
returning hijacked sockets to the web server. For that purpose, use the
|
234
|
-
body streaming API instead (progressively yielding strings via each).
|
235
|
-
|
236
|
-
Servers must ignore the <tt>body</tt> part of the response tuple when
|
237
|
-
the <tt>rack.hijack</tt> response API is in use.
|
238
|
-
|
239
|
-
The special response header <tt>rack.hijack</tt> must only be set
|
240
|
-
if the request env has <tt>rack.hijack?</tt> <tt>true</tt>.
|
241
|
-
==== Conventions
|
242
|
-
* Middleware should not use hijack unless it is handling the whole
|
243
|
-
response.
|
244
|
-
* Middleware may wrap the IO object for the response pattern.
|
245
|
-
* Middleware should not wrap the IO object for the request pattern. The
|
246
|
-
request pattern is intended to provide the hijacker with "raw tcp".
|
247
249
|
== The Response
|
250
|
+
|
248
251
|
=== The Status
|
249
|
-
|
250
|
-
greater than or equal to
|
252
|
+
|
253
|
+
This is an HTTP status. It must be an Integer greater than or equal to
|
254
|
+
100.
|
255
|
+
|
251
256
|
=== The Headers
|
252
|
-
|
257
|
+
|
258
|
+
The headers must be a unfrozen Hash.
|
253
259
|
The header keys must be Strings.
|
254
260
|
Special headers starting "rack." are for communicating with the
|
255
261
|
server, and must not be sent back to the client.
|
256
262
|
The header must not contain a +Status+ key.
|
257
|
-
|
263
|
+
Header keys must conform to RFC7230 token specification, i.e. cannot
|
258
264
|
contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}".
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
265
|
+
Header keys must not contain uppercase ASCII characters (A-Z).
|
266
|
+
Header values must be either a String instance,
|
267
|
+
or an Array of String instances,
|
268
|
+
such that each String instance must not contain characters below 037.
|
269
|
+
|
270
|
+
==== The +content-type+ Header
|
271
|
+
|
272
|
+
There must not be a <tt>content-type</tt> header key when the +Status+ is 1xx,
|
273
|
+
204, or 304.
|
274
|
+
|
275
|
+
==== The +content-length+ Header
|
276
|
+
|
277
|
+
There must not be a <tt>content-length</tt> header key when the
|
278
|
+
+Status+ is 1xx, 204, or 304.
|
279
|
+
|
280
|
+
==== The +rack.protocol+ Header
|
281
|
+
|
282
|
+
If the +rack.protocol+ header is present, it must be a +String+, and
|
283
|
+
must be one of the values from the +rack.protocol+ array from the
|
284
|
+
environment.
|
285
|
+
|
286
|
+
Setting this value informs the server that it should perform a
|
287
|
+
connection upgrade. In HTTP/1, this is done using the +upgrade+
|
288
|
+
header. In HTTP/2, this is done by accepting the request.
|
289
|
+
|
269
290
|
=== The Body
|
270
|
-
The Body must respond to +each+
|
271
|
-
and must only yield String values.
|
272
291
|
|
273
|
-
The Body
|
274
|
-
|
292
|
+
The Body is typically an +Array+ of +String+ instances, an enumerable
|
293
|
+
that yields +String+ instances, a +Proc+ instance, or a File-like
|
294
|
+
object.
|
295
|
+
|
296
|
+
The Body must respond to +each+ or +call+. It may optionally respond
|
297
|
+
to +to_path+ or +to_ary+. A Body that responds to +each+ is considered
|
298
|
+
to be an Enumerable Body. A Body that responds to +call+ is considered
|
299
|
+
to be a Streaming Body.
|
300
|
+
|
301
|
+
A Body that responds to both +each+ and +call+ must be treated as an
|
302
|
+
Enumerable Body, not a Streaming Body. If it responds to +each+, you
|
303
|
+
must call +each+ and not +call+. If the Body doesn't respond to
|
304
|
+
+each+, then you can assume it responds to +call+.
|
275
305
|
|
276
|
-
|
277
|
-
|
278
|
-
|
306
|
+
The Body must either be consumed or returned. The Body is consumed by
|
307
|
+
optionally calling either +each+ or +call+.
|
308
|
+
Then, if the Body responds to +close+, it must be called to release
|
309
|
+
any resources associated with the generation of the body.
|
310
|
+
In other words, +close+ must always be called at least once; typically
|
311
|
+
after the web server has sent the response to the client, but also in
|
312
|
+
cases where the Rack application makes internal/virtual requests and
|
313
|
+
discards the response.
|
279
314
|
|
280
|
-
|
281
|
-
|
315
|
+
|
316
|
+
After calling +close+, the Body is considered closed and should not
|
317
|
+
be consumed again.
|
318
|
+
If the original Body is replaced by a new Body, the new Body must
|
319
|
+
also consume the original Body by calling +close+ if possible.
|
320
|
+
|
321
|
+
If the Body responds to +to_path+, it must return a +String+
|
322
|
+
path for the local file system whose contents are identical
|
282
323
|
to that produced by calling +each+; this may be used by the
|
283
324
|
server as an alternative, possibly more efficient way to
|
284
|
-
transport the response.
|
325
|
+
transport the response. The +to_path+ method does not consume
|
326
|
+
the body.
|
327
|
+
|
328
|
+
==== Enumerable Body
|
329
|
+
|
330
|
+
The Enumerable Body must respond to +each+.
|
331
|
+
It must only be called once.
|
332
|
+
It must not be called after being closed,
|
333
|
+
and must only yield String values.
|
334
|
+
|
335
|
+
Middleware must not call +each+ directly on the Body.
|
336
|
+
Instead, middleware can return a new Body that calls +each+ on the
|
337
|
+
original Body, yielding at least once per iteration.
|
338
|
+
|
339
|
+
If the Body responds to +to_ary+, it must return an +Array+ whose
|
340
|
+
contents are identical to that produced by calling +each+.
|
341
|
+
Middleware may call +to_ary+ directly on the Body and return a new
|
342
|
+
Body in its place. In other words, middleware can only process the
|
343
|
+
Body directly if it responds to +to_ary+. If the Body responds to both
|
344
|
+
+to_ary+ and +close+, its implementation of +to_ary+ must call
|
345
|
+
+close+.
|
346
|
+
|
347
|
+
==== Streaming Body
|
348
|
+
|
349
|
+
The Streaming Body must respond to +call+.
|
350
|
+
It must only be called once.
|
351
|
+
It must not be called after being closed.
|
352
|
+
It takes a +stream+ argument.
|
353
|
+
|
354
|
+
The +stream+ argument must implement:
|
355
|
+
<tt>read, write, <<, flush, close, close_read, close_write, closed?</tt>
|
356
|
+
|
357
|
+
The semantics of these IO methods must be a best effort match to
|
358
|
+
those of a normal Ruby IO or Socket object, using standard arguments
|
359
|
+
and raising standard exceptions. Servers are encouraged to simply
|
360
|
+
pass on real IO objects, although it is recognized that this approach
|
361
|
+
is not directly compatible with HTTP/2.
|
285
362
|
|
286
|
-
The Body commonly is an Array of Strings, the application
|
287
|
-
instance itself, or a File-like object.
|
288
363
|
== Thanks
|
289
|
-
Some parts of this specification are adopted from
|
290
|
-
|
291
|
-
v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank
|
292
|
-
everyone involved in that effort.
|
364
|
+
Some parts of this specification are adopted from {PEP 333 – Python Web Server Gateway Interface v1.0}[https://peps.python.org/pep-0333/]
|
365
|
+
I'd like to thank everyone involved in that effort.
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../constants'
|
4
|
+
|
3
5
|
module Rack
|
4
6
|
module Auth
|
5
7
|
# Rack::Auth::AbstractHandler implements common authentication functionality.
|
@@ -21,7 +23,7 @@ module Rack
|
|
21
23
|
return [ 401,
|
22
24
|
{ CONTENT_TYPE => 'text/plain',
|
23
25
|
CONTENT_LENGTH => '0',
|
24
|
-
'
|
26
|
+
'www-authenticate' => www_authenticate.to_s },
|
25
27
|
[]
|
26
28
|
]
|
27
29
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative '../../request'
|
4
|
+
|
3
5
|
module Rack
|
4
6
|
module Auth
|
5
7
|
class AbstractRequest
|
@@ -25,7 +27,7 @@ module Rack
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def scheme
|
28
|
-
@scheme ||= parts.first
|
30
|
+
@scheme ||= parts.first&.downcase
|
29
31
|
end
|
30
32
|
|
31
33
|
def params
|
data/lib/rack/auth/basic.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require_relative 'abstract/handler'
|
4
4
|
require_relative 'abstract/request'
|
5
|
-
require 'base64'
|
6
5
|
|
7
6
|
module Rack
|
8
7
|
module Auth
|
@@ -10,8 +9,6 @@ module Rack
|
|
10
9
|
#
|
11
10
|
# Initialize with the Rack application that you want protecting,
|
12
11
|
# and a block that checks if a username and password pair are valid.
|
13
|
-
#
|
14
|
-
# See also: <tt>example/protectedlobster.rb</tt>
|
15
12
|
|
16
13
|
class Basic < AbstractHandler
|
17
14
|
|
@@ -48,7 +45,7 @@ module Rack
|
|
48
45
|
end
|
49
46
|
|
50
47
|
def credentials
|
51
|
-
@credentials ||=
|
48
|
+
@credentials ||= params.unpack1('m').split(':', 2)
|
52
49
|
end
|
53
50
|
|
54
51
|
def username
|
data/lib/rack/body_proxy.rb
CHANGED
@@ -15,7 +15,12 @@ module Rack
|
|
15
15
|
|
16
16
|
# Return whether the wrapped body responds to the method.
|
17
17
|
def respond_to_missing?(method_name, include_all = false)
|
18
|
-
|
18
|
+
case method_name
|
19
|
+
when :to_str
|
20
|
+
false
|
21
|
+
else
|
22
|
+
super or @body.respond_to?(method_name, include_all)
|
23
|
+
end
|
19
24
|
end
|
20
25
|
|
21
26
|
# If not already closed, close the wrapped body and
|
@@ -24,7 +29,7 @@ module Rack
|
|
24
29
|
return if @closed
|
25
30
|
@closed = true
|
26
31
|
begin
|
27
|
-
@body.close if @body.respond_to?
|
32
|
+
@body.close if @body.respond_to?(:close)
|
28
33
|
ensure
|
29
34
|
@block.call
|
30
35
|
end
|
@@ -38,8 +43,21 @@ module Rack
|
|
38
43
|
|
39
44
|
# Delegate missing methods to the wrapped body.
|
40
45
|
def method_missing(method_name, *args, &block)
|
41
|
-
|
46
|
+
case method_name
|
47
|
+
when :to_str
|
48
|
+
super
|
49
|
+
when :to_ary
|
50
|
+
begin
|
51
|
+
@body.__send__(method_name, *args, &block)
|
52
|
+
ensure
|
53
|
+
close
|
54
|
+
end
|
55
|
+
else
|
56
|
+
@body.__send__(method_name, *args, &block)
|
57
|
+
end
|
42
58
|
end
|
59
|
+
# :nocov:
|
43
60
|
ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
|
61
|
+
# :nocov:
|
44
62
|
end
|
45
63
|
end
|