Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 265 lines (264 sloc) 14.372 kb
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
1 This specification aims to formalize the Rack protocol. You
2 can (and should) use Rack::Lint to enforce it.
3 When you develop middleware, be sure to add a Lint before and
4 after to catch all mistakes.
5 = Rack applications
85312d6 @raggi Update SPEC
raggi authored
6 A Rack application is a Ruby object (not a class) that
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
7 responds to +call+.
8 It takes exactly one argument, the *environment*
9 and returns an Array of exactly three values:
10 The *status*,
11 the *headers*,
12 and the *body*.
13 == The Environment
14 The environment must be an instance of Hash that includes
15 CGI-like headers. The application is free to modify the
16 environment.
17 The environment is required to include these variables
18 (adopted from PEP333), except when they'd be empty, but see
19 below.
20 <tt>REQUEST_METHOD</tt>:: The HTTP request method, such as
21 "GET" or "POST". This cannot ever
22 be an empty string, and so is
23 always required.
24 <tt>SCRIPT_NAME</tt>:: The initial portion of the request
25 URL's "path" that corresponds to the
26 application object, so that the
27 application knows its virtual
28 "location". This may be an empty
29 string, if the application corresponds
30 to the "root" of the server.
31 <tt>PATH_INFO</tt>:: The remainder of the request URL's
32 "path", designating the virtual
33 "location" of the request's target
34 within the application. This may be an
35 empty string, if the request URL targets
36 the application root and does not have a
37 trailing slash. This value may be
2ffefc6 @yeonhoyoon fix typo
yeonhoyoon authored
38 percent-encoded when originating from
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
39 a URL.
40 <tt>QUERY_STRING</tt>:: The portion of the request URL that
41 follows the <tt>?</tt>, if any. May be
42 empty, but is always required!
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
43 <tt>SERVER_NAME</tt>, <tt>SERVER_PORT</tt>::
44 When combined with <tt>SCRIPT_NAME</tt> and
45 <tt>PATH_INFO</tt>, these variables can be
46 used to complete the URL. Note, however,
47 that <tt>HTTP_HOST</tt>, if present,
48 should be used in preference to
49 <tt>SERVER_NAME</tt> for reconstructing
50 the request URL.
51 <tt>SERVER_NAME</tt> and <tt>SERVER_PORT</tt>
52 can never be empty strings, and so
53 are always required.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
54 <tt>HTTP_</tt> Variables:: Variables corresponding to the
55 client-supplied HTTP request
56 headers (i.e., variables whose
57 names begin with <tt>HTTP_</tt>). The
58 presence or absence of these
59 variables should correspond with
60 the presence or absence of the
61 appropriate HTTP header in the
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
62 request. See
63 <a href="https://tools.ietf.org/html/rfc3875#section-4.1.18">
64 RFC3875 section 4.1.18</a> for
65 specific behavior.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
66 In addition to this, the Rack environment must include these
67 Rack-specific variables:
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
68 <tt>rack.version</tt>:: The Array representing this version of Rack
69 See Rack::VERSION, that corresponds to
70 the version of this SPEC.
71 <tt>rack.url_scheme</tt>:: +http+ or +https+, depending on the
72 request URL.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
73 <tt>rack.input</tt>:: See below, the input stream.
74 <tt>rack.errors</tt>:: See below, the error stream.
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
75 <tt>rack.multithread</tt>:: true if the application object may be
76 simultaneously invoked by another thread
77 in the same process, false otherwise.
78 <tt>rack.multiprocess</tt>:: true if an equivalent application object
79 may be simultaneously invoked by another
80 process, false otherwise.
81 <tt>rack.run_once</tt>:: true if the server expects
82 (but does not guarantee!) that the
83 application will only be invoked this one
84 time during the life of its containing
85 process. Normally, this will only be true
86 for a server based on CGI
87 (or something similar).
88 <tt>rack.hijack?</tt>:: present and true if the server supports
89 connection hijacking. See below, hijacking.
90 <tt>rack.hijack</tt>:: an object responding to #call that must be
91 called at least once before using
92 rack.hijack_io.
93 It is recommended #call return rack.hijack_io
94 as well as setting it in env if necessary.
95 <tt>rack.hijack_io</tt>:: if rack.hijack? is true, and rack.hijack
96 has received #call, this will contain
97 an object resembling an IO. See hijacking.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
98 Additional environment specifications have approved to
99 standardized middleware APIs. None of these are required to
100 be implemented by the server.
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
101 <tt>rack.session</tt>:: A hash like interface for storing
102 request session data.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
103 The store must implement:
104 store(key, value) (aliased as []=);
105 fetch(key, default = nil) (aliased as []);
106 delete(key);
107 clear;
108 <tt>rack.logger</tt>:: A common object interface for logging messages.
109 The object must implement:
110 info(message, &block)
111 debug(message, &block)
112 warn(message, &block)
113 error(message, &block)
114 fatal(message, &block)
a604924 @codekitchen add rack.multipart options to lint and SPEC
codekitchen authored
115 <tt>rack.multipart.buffer_size</tt>:: An Integer hint to the multipart parser as to what chunk size to use for reads and writes.
116 <tt>rack.multipart.tempfile_factory</tt>:: An object responding to #call with two arguments, the filename and content_type given for the multipart form field, and returning an IO-like object that responds to #<< and optionally #rewind. This factory will be used to instantiate the tempfile for each multipart form file upload field, rather than the default class of Tempfile.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
117 The server or the application can store their own data in the
118 environment, too. The keys must contain at least one dot,
119 and should be prefixed uniquely. The prefix <tt>rack.</tt>
120 is reserved for use with the Rack core distribution and other
121 accepted specifications and must not be used otherwise.
122 The environment must not contain the keys
123 <tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt>
124 (use the versions without <tt>HTTP_</tt>).
125 The CGI keys (named without a period) must have String values.
126 There are the following restrictions:
127 * <tt>rack.version</tt> must be an array of Integers.
128 * <tt>rack.url_scheme</tt> must either be +http+ or +https+.
129 * There must be a valid input stream in <tt>rack.input</tt>.
130 * There must be a valid error stream in <tt>rack.errors</tt>.
36a2145 @raggi Straw man for rack.hijack*, connection hijacking!
raggi authored
131 * There may be a valid hijack stream in <tt>rack.hijack_io</tt>
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
132 * The <tt>REQUEST_METHOD</tt> must be a valid token.
133 * The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
134 * The <tt>PATH_INFO</tt>, if non-empty, must start with <tt>/</tt>
135 * The <tt>CONTENT_LENGTH</tt>, if given, must consist of digits only.
136 * One of <tt>SCRIPT_NAME</tt> or <tt>PATH_INFO</tt> must be
137 set. <tt>PATH_INFO</tt> should be <tt>/</tt> if
138 <tt>SCRIPT_NAME</tt> is empty.
139 <tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
140 === The Input Stream
141 The input stream is an IO-like object which contains the raw HTTP
142 POST data.
143 When applicable, its external encoding must be "ASCII-8BIT" and it
144 must be opened in binary mode, for Ruby 1.9 compatibility.
145 The input stream must respond to +gets+, +each+, +read+ and +rewind+.
146 * +gets+ must be called without arguments and return a string,
147 or +nil+ on EOF.
05c96e7 @ArtemPyanykh Reformat Rack::Lint docs.
ArtemPyanykh authored
148 * +read+ behaves like IO#read.
149 Its signature is <tt>read([length, [buffer]])</tt>.
150 If given, +length+ must be a non-negative Integer (>= 0) or +nil+,
151 and +buffer+ must be a String and may not be nil.
152 If +length+ is given and not nil, then this method reads at most
153 +length+ bytes from the input stream.
154 If +length+ is not given or nil, then this method reads
155 all data until EOF.
156 When EOF is reached, this method returns nil if +length+ is given
157 and not nil, or "" if +length+ is not given or is nil.
158 If +buffer+ is given, then the read data will be placed
159 into +buffer+ instead of a newly created String object.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
160 * +each+ must be called without arguments and only yield Strings.
161 * +rewind+ must be called without arguments. It rewinds the input
162 stream back to the beginning. It must not raise Errno::ESPIPE:
163 that is, it may not be a pipe or a socket. Therefore, handler
164 developers must buffer the input data into some rewindable object
165 if the underlying input stream is not rewindable.
166 * +close+ must never be called on the input stream.
167 === The Error Stream
168 The error stream must respond to +puts+, +write+ and +flush+.
169 * +puts+ must be called with a single argument that responds to +to_s+.
170 * +write+ must be called with a single argument that is a String.
171 * +flush+ must be called without arguments and must be called
172 in order to make the error appear for sure.
173 * +close+ must never be called on the error stream.
36a2145 @raggi Straw man for rack.hijack*, connection hijacking!
raggi authored
174 === Hijacking
8a311fb @raggi Add straw man for the after-headers hijack
raggi authored
175 ==== Request (before status)
36a2145 @raggi Straw man for rack.hijack*, connection hijacking!
raggi authored
176 If rack.hijack? is true then rack.hijack must respond to #call.
c33efb8 @raggi Hijack SPEC changes after review discussion
raggi authored
177 rack.hijack must return the io that will also be assigned (or is
36a2145 @raggi Straw man for rack.hijack*, connection hijacking!
raggi authored
178 already present, in rack.hijack_io.
179 rack.hijack_io must respond to:
180 <tt>read, write, read_nonblock, write_nonblock, flush, close,
181 close_read, close_write, closed?</tt>
182 The semantics of these IO methods must be a best effort match to
183 those of a normal ruby IO or Socket object, using standard
184 arguments and raising standard exceptions. Servers are encouraged
185 to simply pass on real IO objects, although it is recognized that
186 this approach is not directly compatible with SPDY and HTTP 2.0.
187 IO provided in rack.hijack_io should preference the
188 IO::WaitReadable and IO::WaitWritable APIs wherever supported.
189 There is a deliberate lack of full specification around
190 rack.hijack_io, as semantics will change from server to server.
191 Users are encouraged to utilize this API with a knowledge of their
192 server choice, and servers may extend the functionality of
193 hijack_io to provide additional features to users. The purpose of
194 rack.hijack is for Rack to "get out of the way", as such, Rack only
195 provides the minimum of specification and support.
196 If rack.hijack? is false, then rack.hijack should not be set.
197 If rack.hijack? is false, then rack.hijack_io should not be set.
8a311fb @raggi Add straw man for the after-headers hijack
raggi authored
198 ==== Response (after headers)
199 It is also possible to hijack a response after the status and headers
200 have been sent.
201 In order to do this, an application may set the special header
202 <tt>rack.hijack</tt> to an object that responds to <tt>call</tt>
203 accepting an argument that conforms to the <tt>rack.hijack_io</tt>
204 protocol.
205 After the headers have been sent, and this hijack callback has been
206 called, the application is now responsible for the remaining lifecycle
207 of the IO. The application is also responsible for maintaining HTTP
208 semantics. Of specific note, in almost all cases in the current SPEC,
209 applications will have wanted to specify the header Connection:close in
210 HTTP/1.1, and not Connection:keep-alive, as there is no protocol for
211 returning hijacked sockets to the web server. For that purpose, use the
212 body streaming API instead (progressively yielding strings via each).
213 Servers must ignore the <tt>body</tt> part of the response tuple when
214 the <tt>rack.hijack</tt> response API is in use.
215 The special response header <tt>rack.hijack</tt> must only be set
216 if the request env has <tt>rack.hijack?</tt> <tt>true</tt>.
c33efb8 @raggi Hijack SPEC changes after review discussion
raggi authored
217 ==== Conventions
218 * Middleware should not use hijack unless it is handling the whole
219 response.
220 * Middleware may wrap the IO object for the response pattern.
221 * Middleware should not wrap the IO object for the request pattern. The
222 request pattern is intended to provide the hijacker with "raw tcp".
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
223 == The Response
224 === The Status
225 This is an HTTP status. When parsed as integer (+to_i+), it must be
226 greater than or equal to 100.
227 === The Headers
228 The header must respond to +each+, and yield values of key and value.
8a311fb @raggi Add straw man for the after-headers hijack
raggi authored
229 Special headers starting "rack." are for communicating with the
230 server, and must not be sent back to the client.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
231 The header keys must be Strings.
6839fc2 @raggi Rack::Lint and SPEC align with RFC7230 headers
raggi authored
232 The header must not contain a +Status+ key.
233 The header must conform to RFC7230 token specification, i.e. cannot
234 contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}".
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
235 The values of the header must be Strings,
236 consisting of lines (for multiple header values, e.g. multiple
c3ccaf5 @obfusk fix \n in spec
obfusk authored
237 <tt>Set-Cookie</tt> values) separated by "\\n".
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
238 The lines must not contain characters below 037.
239 === The Content-Type
2138f0b @raggi Cleanup Lint Content-Type section after 3623d04
raggi authored
240 There must not be a <tt>Content-Type</tt>, when the +Status+ is 1xx,
241 204, 205 or 304.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
242 === The Content-Length
243 There must not be a <tt>Content-Length</tt> header when the
2c5b076 @dkubb Add 205 Reset Content to the list of statuses without a message body
dkubb authored
244 +Status+ is 1xx, 204, 205 or 304.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
245 === The Body
246 The Body must respond to +each+
247 and must only yield String values.
248 The Body itself should not be an instance of String, as this will
249 break in Ruby 1.9.
90650c1 @raggi Clarify the body.close spec section
raggi authored
250 If the Body responds to +close+, it will be called after iteration. If
251 the body is replaced by a middleware after action, the original body
e7d741c @vipulnsward Fix some typos
vipulnsward authored
252 must be closed first, if it responds to close.
859ab9f @raggi Adding SPEC with rake task dependencies
raggi authored
253 If the Body responds to +to_path+, it must return a String
254 identifying the location of a file whose contents are identical
255 to that produced by calling +each+; this may be used by the
256 server as an alternative, possibly more efficient way to
257 transport the response.
258 The Body commonly is an Array of Strings, the application
259 instance itself, or a File-like object.
260 == Thanks
261 Some parts of this specification are adopted from PEP333: Python
262 Web Server Gateway Interface
263 v1.0 (http://www.python.org/dev/peps/pep-0333/). I'd like to thank
264 everyone involved in that effort.
Something went wrong with that request. Please try again.