Skip to content
Browse files

Fix SPEC formatting.

  • Loading branch information
ioquatix committed Feb 6, 2020
1 parent 4e8324b commit 5cdea4f6ded1e77a8077945ccee0950aedf25279
Showing with 23 additions and 1 deletion.
  1. +1 −1 Rakefile
  2. +22 −0 SPEC.rdoc
@@ -78,7 +78,7 @@ file 'lib/rack/lint.rb'
file "SPEC.rdoc" => 'lib/rack/lint.rb' do"SPEC.rdoc", "wb") { |file|
IO.foreach("lib/rack/lint.rb") { |line|
if line =~ /## (.*)/
if line =~ /^\s*## ?(.*)/
file.puts $1
@@ -1,5 +1,6 @@
This specification aims to formalize the Rack protocol. You
can (and should) use Rack::Lint to enforce it.

When you develop middleware, be sure to add a Lint before and
after to catch all mistakes.
= Rack applications
@@ -14,6 +15,7 @@ and the *body*.
The environment must be an unfrozen instance of Hash that includes
CGI-like headers. The application is free to modify the

The environment is required to include these variables
(adopted from PEP333), except when they'd be empty, but see
@@ -119,6 +121,7 @@ environment, too. The keys must contain at least one dot,
and should be prefixed uniquely. The prefix <tt>rack.</tt>
is reserved for use with the Rack core distribution and other
accepted specifications and must not be used otherwise.

The environment must not contain the keys
(use the versions without <tt>HTTP_</tt>).
@@ -140,6 +143,7 @@ There are the following restrictions:
<tt>SCRIPT_NAME</tt> is empty.
<tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
=== The Input Stream

The input stream is an IO-like object which contains the raw HTTP
POST data.
When applicable, its external encoding must be "ASCII-8BIT" and it
@@ -149,14 +153,19 @@ The input stream must respond to +gets+, +each+, +read+ and +rewind+.
or +nil+ on EOF.
* +read+ behaves like IO#read.
Its signature is <tt>read([length, [buffer]])</tt>.

If given, +length+ must be a non-negative Integer (>= 0) or +nil+,
and +buffer+ must be a String and may not be nil.

If +length+ is given and not nil, then this method reads at most
+length+ bytes from the input stream.

If +length+ is not given or nil, then this method reads
all data until EOF.

When EOF is reached, this method returns nil if +length+ is given
and not nil, or "" if +length+ is not given or is nil.

If +buffer+ is given, then the read data will be placed
into +buffer+ instead of a newly created String object.
* +each+ must be called without arguments and only yield Strings.
@@ -178,24 +187,30 @@ The error stream must respond to +puts+, +write+ and +flush+.
If rack.hijack? is true then rack.hijack must respond to #call.
rack.hijack must return the io that will also be assigned (or is
already present, in rack.hijack_io.

rack.hijack_io must respond to:
<tt>read, write, read_nonblock, write_nonblock, flush, close,
close_read, close_write, closed?</tt>

The semantics of these IO methods must be a best effort match to
those of a normal ruby IO or Socket object, using standard
arguments and raising standard exceptions. Servers are encouraged
to simply pass on real IO objects, although it is recognized that
this approach is not directly compatible with SPDY and HTTP 2.0.

IO provided in rack.hijack_io should preference the
IO::WaitReadable and IO::WaitWritable APIs wherever supported.

There is a deliberate lack of full specification around
rack.hijack_io, as semantics will change from server to server.
Users are encouraged to utilize this API with a knowledge of their
server choice, and servers may extend the functionality of
hijack_io to provide additional features to users. The purpose of
rack.hijack is for Rack to "get out of the way", as such, Rack only
provides the minimum of specification and support.

If rack.hijack? is false, then rack.hijack should not be set.

If rack.hijack? is false, then rack.hijack_io should not be set.
==== Response (after headers)
It is also possible to hijack a response after the status and headers
@@ -204,6 +219,7 @@ In order to do this, an application may set the special header
<tt>rack.hijack</tt> to an object that responds to <tt>call</tt>
accepting an argument that conforms to the <tt>rack.hijack_io</tt>

After the headers have been sent, and this hijack callback has been
called, the application is now responsible for the remaining lifecycle
of the IO. The application is also responsible for maintaining HTTP
@@ -212,8 +228,10 @@ applications will have wanted to specify the header Connection:close in
HTTP/1.1, and not Connection:keep-alive, as there is no protocol for
returning hijacked sockets to the web server. For that purpose, use the
body streaming API instead (progressively yielding strings via each).

Servers must ignore the <tt>body</tt> part of the response tuple when
the <tt>rack.hijack</tt> response API is in use.

The special response header <tt>rack.hijack</tt> must only be set
if the request env has <tt>rack.hijack?</tt> <tt>true</tt>.
==== Conventions
@@ -247,16 +265,20 @@ There must not be a <tt>Content-Length</tt> header when the
=== The Body
The Body must respond to +each+
and must only yield String values.

The Body itself should not be an instance of String, as this will
break in Ruby 1.9.

If the Body responds to +close+, it will be called after iteration. If
the body is replaced by a middleware after action, the original body
must be closed first, if it responds to close.

If the Body responds to +to_path+, it must return a String
identifying the location of a file whose contents are identical
to that produced by calling +each+; this may be used by the
server as an alternative, possibly more efficient way to
transport the response.

The Body commonly is an Array of Strings, the application
instance itself, or a File-like object.
== Thanks

0 comments on commit 5cdea4f

Please sign in to comment.
You can’t perform that action at this time.