318 lines
9.7 KiB
HTML
318 lines
9.7 KiB
HTML
|
<?xml version="1.0" encoding="utf-8"?>
|
||
|
<!DOCTYPE html
|
||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||
|
<head>
|
||
|
<title>File: SPEC</title>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||
|
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
||
|
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
||
|
<script type="text/javascript">
|
||
|
// <![CDATA[
|
||
|
|
||
|
function popupCode( url ) {
|
||
|
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
||
|
}
|
||
|
|
||
|
function toggleCode( id ) {
|
||
|
if ( document.getElementById )
|
||
|
elem = document.getElementById( id );
|
||
|
else if ( document.all )
|
||
|
elem = eval( "document.all." + id );
|
||
|
else
|
||
|
return false;
|
||
|
|
||
|
elemStyle = elem.style;
|
||
|
|
||
|
if ( elemStyle.display != "block" ) {
|
||
|
elemStyle.display = "block"
|
||
|
} else {
|
||
|
elemStyle.display = "none"
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Make codeblocks hidden by default
|
||
|
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
||
|
|
||
|
// ]]>
|
||
|
</script>
|
||
|
|
||
|
</head>
|
||
|
<body>
|
||
|
|
||
|
|
||
|
|
||
|
<div id="fileHeader">
|
||
|
<h1>SPEC</h1>
|
||
|
<table class="header-table">
|
||
|
<tr class="top-aligned-row">
|
||
|
<td><strong>Path:</strong></td>
|
||
|
<td>SPEC
|
||
|
</td>
|
||
|
</tr>
|
||
|
<tr class="top-aligned-row">
|
||
|
<td><strong>Last Update:</strong></td>
|
||
|
<td>Fri Jan 09 17:40:06 +0100 2009</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
<!-- banner header -->
|
||
|
|
||
|
<div id="bodyContent">
|
||
|
|
||
|
|
||
|
|
||
|
<div id="contextContent">
|
||
|
|
||
|
<div id="description">
|
||
|
<p>
|
||
|
This specification aims to formalize the <a
|
||
|
href="../classes/Rack.html">Rack</a> protocol. You can (and should) use <a
|
||
|
href="../classes/Rack/Lint.html">Rack::Lint</a> to enforce it. When you
|
||
|
develop middleware, be sure to add a Lint before and after to catch all
|
||
|
mistakes.
|
||
|
</p>
|
||
|
<h1><a href="../classes/Rack.html">Rack</a> applications</h1>
|
||
|
<p>
|
||
|
A <a href="../classes/Rack.html">Rack</a> application is an Ruby object
|
||
|
(not a class) that responds to <tt>call</tt>. It takes exactly one
|
||
|
argument, the <b>environment</b> and returns an Array of exactly three
|
||
|
values: The <b>status</b>, the <b>headers</b>, and the <b>body</b>.
|
||
|
</p>
|
||
|
<h2>The Environment</h2>
|
||
|
<p>
|
||
|
The environment must be an true instance of Hash (no subclassing allowed)
|
||
|
that includes CGI-like headers. The application is free to modify the
|
||
|
environment. The environment is required to include these variables
|
||
|
(adopted from PEP333), except when they‘d be empty, but see below.
|
||
|
</p>
|
||
|
<table>
|
||
|
<tr><td valign="top"><tt>REQUEST_METHOD</tt>:</td><td>The HTTP request method, such as "GET" or "POST". This
|
||
|
cannot ever be an empty string, and so is always required.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>SCRIPT_NAME</tt>:</td><td>The initial portion of the request URL‘s "path" that
|
||
|
corresponds to the application object, so that the application knows its
|
||
|
virtual "location". This may be an empty string, if the
|
||
|
application corresponds to the "root" of the server.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>PATH_INFO</tt>:</td><td>The remainder of the request URL‘s "path", designating the
|
||
|
virtual "location" of the request‘s target within the
|
||
|
application. This may be an empty string, if the request URL targets the
|
||
|
application root and does not have a trailing slash.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>QUERY_STRING</tt>:</td><td>The portion of the request URL that follows the <tt>?</tt>, if any. May be
|
||
|
empty, but is always required!
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>SERVER_NAME</tt>, <tt>SERVER_PORT</tt>:</td><td>When combined with <tt>SCRIPT_NAME</tt> and <tt>PATH_INFO</tt>, these
|
||
|
variables can be used to complete the URL. Note, however, that
|
||
|
<tt>HTTP_HOST</tt>, if present, should be used in preference to
|
||
|
<tt>SERVER_NAME</tt> for reconstructing the request URL.
|
||
|
<tt>SERVER_NAME</tt> and <tt>SERVER_PORT</tt> can never be empty strings,
|
||
|
and so are always required.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>HTTP_</tt> Variables:</td><td>Variables corresponding to the client-supplied HTTP request headers (i.e.,
|
||
|
variables whose names begin with <tt>HTTP_</tt>). The presence or absence
|
||
|
of these variables should correspond with the presence or absence of the
|
||
|
appropriate HTTP header in the request.
|
||
|
|
||
|
</td></tr>
|
||
|
</table>
|
||
|
<p>
|
||
|
In addition to this, the <a href="../classes/Rack.html">Rack</a>
|
||
|
environment must include these <a
|
||
|
href="../classes/Rack.html">Rack</a>-specific variables:
|
||
|
</p>
|
||
|
<table>
|
||
|
<tr><td valign="top"><tt>rack.version</tt>:</td><td>The Array [0,1], representing this version of <a
|
||
|
href="../classes/Rack.html">Rack</a>.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.url_scheme</tt>:</td><td><tt>http</tt> or <tt>https</tt>, depending on the request URL.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.input</tt>:</td><td>See below, the input stream.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.errors</tt>:</td><td>See below, the error stream.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.multithread</tt>:</td><td>true if the application object may be simultaneously invoked by another
|
||
|
thread in the same process, false otherwise.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.multiprocess</tt>:</td><td>true if an equivalent application object may be simultaneously invoked by
|
||
|
another process, false otherwise.
|
||
|
|
||
|
</td></tr>
|
||
|
<tr><td valign="top"><tt>rack.run_once</tt>:</td><td>true if the server expects (but does not guarantee!) that the application
|
||
|
will only be invoked this one time during the life of its containing
|
||
|
process. Normally, this will only be true for a server based on CGI (or
|
||
|
something similar).
|
||
|
|
||
|
</td></tr>
|
||
|
</table>
|
||
|
<p>
|
||
|
The server or the application can store their own data in the 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 <a
|
||
|
href="../classes/Rack.html">Rack</a> core distribution and must not be used
|
||
|
otherwise. The environment must not contain the keys
|
||
|
<tt>HTTP_CONTENT_TYPE</tt> or <tt>HTTP_CONTENT_LENGTH</tt> (use the
|
||
|
versions without <tt>HTTP_</tt>). The CGI keys (named without a period)
|
||
|
must have String values. There are the following restrictions:
|
||
|
</p>
|
||
|
<ul>
|
||
|
<li><tt>rack.version</tt> must be an array of Integers.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>rack.url_scheme</tt> must either be <tt>http</tt> or <tt>https</tt>.
|
||
|
|
||
|
</li>
|
||
|
<li>There must be a valid input stream in <tt>rack.input</tt>.
|
||
|
|
||
|
</li>
|
||
|
<li>There must be a valid error stream in <tt>rack.errors</tt>.
|
||
|
|
||
|
</li>
|
||
|
<li>The <tt>REQUEST_METHOD</tt> must be a valid token.
|
||
|
|
||
|
</li>
|
||
|
<li>The <tt>SCRIPT_NAME</tt>, if non-empty, must start with <tt>/</tt>
|
||
|
|
||
|
</li>
|
||
|
<li>The <tt>PATH_INFO</tt>, if non-empty, must start with <tt>/</tt>
|
||
|
|
||
|
</li>
|
||
|
<li>The <tt>CONTENT_LENGTH</tt>, if given, must consist of digits only.
|
||
|
|
||
|
</li>
|
||
|
<li>One of <tt>SCRIPT_NAME</tt> or <tt>PATH_INFO</tt> must be set.
|
||
|
<tt>PATH_INFO</tt> should be <tt>/</tt> if <tt>SCRIPT_NAME</tt> is empty.
|
||
|
<tt>SCRIPT_NAME</tt> never should be <tt>/</tt>, but instead be empty.
|
||
|
|
||
|
</li>
|
||
|
</ul>
|
||
|
<h3>The Input Stream</h3>
|
||
|
<p>
|
||
|
The input stream must respond to <tt>gets</tt>, <tt>each</tt> and
|
||
|
<tt>read</tt>.
|
||
|
</p>
|
||
|
<ul>
|
||
|
<li><tt>gets</tt> must be called without arguments and return a string, or
|
||
|
<tt>nil</tt> on EOF.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>read</tt> must be called without or with one integer argument and
|
||
|
return a string, or <tt>nil</tt> on EOF.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>each</tt> must be called without arguments and only yield Strings.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>close</tt> must never be called on the input stream.
|
||
|
|
||
|
</li>
|
||
|
</ul>
|
||
|
<h3>The Error Stream</h3>
|
||
|
<p>
|
||
|
The error stream must respond to <tt>puts</tt>, <tt>write</tt> and
|
||
|
<tt>flush</tt>.
|
||
|
</p>
|
||
|
<ul>
|
||
|
<li><tt>puts</tt> must be called with a single argument that responds to
|
||
|
<tt>to_s</tt>.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>write</tt> must be called with a single argument that is a String.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>flush</tt> must be called without arguments and must be called in order
|
||
|
to make the error appear for sure.
|
||
|
|
||
|
</li>
|
||
|
<li><tt>close</tt> must never be called on the error stream.
|
||
|
|
||
|
</li>
|
||
|
</ul>
|
||
|
<h2>The Response</h2>
|
||
|
<h3>The Status</h3>
|
||
|
<p>
|
||
|
The status, if parsed as integer (<tt>to_i</tt>), must be greater than or
|
||
|
equal to 100.
|
||
|
</p>
|
||
|
<h3>The Headers</h3>
|
||
|
<p>
|
||
|
The header must respond to each, and yield values of key and value. The
|
||
|
header keys must be Strings. The header must not contain a <tt>Status</tt>
|
||
|
key, contain keys with <tt>:</tt> or newlines in their name, contain keys
|
||
|
names that end in <tt>-</tt> or <tt>_</tt>, but only contain keys that
|
||
|
consist of letters, digits, <tt>_</tt> or <tt>-</tt> and start with a
|
||
|
letter. The values of the header must respond to each. The values passed on
|
||
|
each must be Strings and not contain characters below 037.
|
||
|
</p>
|
||
|
<h3>The Content-Type</h3>
|
||
|
<p>
|
||
|
There must be a <tt>Content-Type</tt>, except when the <tt>Status</tt> is
|
||
|
1xx, 204 or 304, in which case there must be none given.
|
||
|
</p>
|
||
|
<h3>The Content-Length</h3>
|
||
|
<p>
|
||
|
There must be a <tt>Content-Length</tt>, except when the <tt>Status</tt> is
|
||
|
1xx, 204 or 304, in which case there must be none given.
|
||
|
</p>
|
||
|
<h3>The Body</h3>
|
||
|
<p>
|
||
|
The Body must respond to each and must only yield String values. If the
|
||
|
Body responds to close, it will be called after iteration. The Body
|
||
|
commonly is an Array of Strings, the application instance itself, or a
|
||
|
File-like object.
|
||
|
</p>
|
||
|
<h2>Thanks</h2>
|
||
|
<p>
|
||
|
Some parts of this specification are adopted from PEP333: Python Web Server
|
||
|
Gateway Interface v1.0 (<a
|
||
|
href="http://www.python.org/dev/peps/pep-0333">www.python.org/dev/peps/pep-0333</a>/).
|
||
|
I‘d like to thank everyone involved in that effort.
|
||
|
</p>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<!-- if includes -->
|
||
|
|
||
|
<div id="section">
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<!-- if method_list -->
|
||
|
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div id="validator-badges">
|
||
|
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
||
|
</div>
|
||
|
|
||
|
</body>
|
||
|
</html>
|