@@ -5,10 +5,10 @@
55This module defines a generic web application interface. It is a common
66protocol between web servers and web applications.
77
8−The overriding design principles here are performance, generality and type
9−safety. To address performance, this library is built on 'Source' for the
10−request body and 'Enumerator' for the response bodies. The advantages of this
11−approach over lazy IO have been debated elsewhere.
8+The overriding design principles here are performance and generality . To
9+address performance, this library is built on 'Source' for the request body and
10+'Enumerator' for the response bodies. The advantages of this approach over lazy
11+IO have been debated elsewhere.
1212
1313Nonetheless, many people find these data structures difficult to work with. For
1414that reason, this library includes the "Network.Wai.Enumerator" module to
@@ -18,11 +18,8 @@ Generality is achieved by removing many variables commonly found in similar
1818projects that are not universal to all servers. The goal is that the 'Request'
1919object contains only data which is meaningful in all circumstances.
2020
21−Unlike other approaches, this package declares many data types to assist in
22−type safety. This feels more inline with the general Haskell spirit.
23−
2421A final note: please remember when using this package that, while your
25−application my compile without a hitch against many different servers, there
22+application may compile without a hitch against many different servers, there
2623are other considerations to be taken when moving to a new backend. For example,
2724if you transfer from a CGI application to a FastCGI one, you might suddenly
2825find you have a memory leak. Conversely, a FastCGI application would be
@@ -33,7 +30,6 @@ would kill the performance of a CGI application.
3330module Network.Wai
3431 ( -- * Data types
3532
36− -- $show_read
3733 -- ** Request method
3834 Method
3935 -- ** HTTP protocol versions
@@ -79,37 +75,42 @@ import qualified Data.ByteString.Lazy as L
7975import Data.Char (toLower)
8076import Data.String (IsString (..))
8177
82−-- $show_read
83−--
84−-- For the data types below, you should only use the 'Show' and 'Read'
85−-- instances for debugging purposes. Each datatype (excepting 'UrlScheme') has
86−-- associated functions for converting to and from strict 'B.ByteString's;
87−-- these are approrpiate for generating content.
88−
89−-- | HTTP request method. This data type is extensible via the Method
90−-- constructor. Request methods are case-sensitive, and comparison is achieved
91−-- by converting to a 'B.ByteString' via 'methodToBS'.
78+-- | HTTP request method. Since the HTTP protocol allows arbitrary request
79+-- methods, we leave this open as a 'B.ByteString'. Please note the request
80+-- methods are case-sensitive.
9281type Method = B.ByteString
9382
94−-- | Version of HTTP protocol used in current request. This data type is
95−-- extensible via the HttpVersion constructor. Comparison is achieved by
96−-- converting to a 'B.ByteString' via 'httpVersionToBS'.
83+-- | Version of HTTP protocol used in current request. The value given here
84+-- should be everything following the \"HTTP/\" line in a request. In other
85+-- words, HTTP\/1.1 -> \"1.1\", HTTP\/1.0 -> \"1.0\".
9786type HttpVersion = B.ByteString
9887
88+-- | HTTP/0.9
9989http09 :: HttpVersion
10090http09 = B8.pack "0.9"
10191
92+-- | HTTP/1.0
10293http10 :: HttpVersion
10394http10 = B8.pack "1.0"
10495
96+-- | HTTP/1.1
10597http11 :: HttpVersion
10698http11 = B8.pack "1.1"
10799
100+-- | A case insensitive bytestring, where the 'Eq' and 'Ord' instances do
101+-- comparisons based on the lower-cased version of this string. For efficiency,
102+-- this datatype contains both the original and lower-case version of the
103+-- string; this means there is no need to lower-case the bytestring for every
104+-- comparison.
105+--
106+-- Please note that this datatype has an 'IsString' instance, which can allow
107+-- for very concise code when using the OverloadedStrings language extension.
108108data CIByteString = CIByteString
109109 { ciOriginal :: !B.ByteString
110110 , ciLowerCase :: !B.ByteString
111111 }
112112
113+-- | Convert a regular bytestring to a case-insensitive bytestring.
113114mkCIByteString :: B.ByteString -> CIByteString
114115mkCIByteString bs = CIByteString bs $ B8.map toLower bs
115116
@@ -122,68 +123,59 @@ instance Ord CIByteString where
122123instance IsString CIByteString where
123124 fromString = mkCIByteString . fromString
124125
125−-- | Headers sent from the client to the server. Clearly, this is not a
126−-- complete list of all possible headers, but rather a selection of common
127−-- ones. If other headers are required, they can be created with the
128−-- RequestHeader constructor.
129−--
130−-- The naming rules are simple: removing any hyphens from the actual name, and
131−-- if there is a naming conflict with a 'ResponseHeader', prefix with Req.
132−--
133−-- Equality determined by conversion via 'requestHeaderToLower'. Request
134−-- headers are *not* case sensitive (a change from version 0.0 of WAI).
126+-- | Headers sent from the client to the server. Note that this is a
127+-- case-insensitive string, as the HTTP spec specifies.
135128type RequestHeader = CIByteString
136129
137−-- | Headers sent from the server to the client. Clearly, this is not a
138−-- complete list of all possible headers, but rather a selection of common
139−-- ones. If other headers are required, they can be created with the
140−-- ResponseHeader constructor.
141−--
142−-- if there is a naming conflict with a 'ResponseHeader', prefix with Req.
143−--
144−-- Equality determined by conversion via 'responseHeaderToLower'. Response
145−-- headers are *not* case sensitive (a change from version 0.0 of WAI).
130+-- | Headers sent from the server to the client. Note that this is a
131+-- case-insensitive string, as the HTTP spec specifies.
146132type ResponseHeader = CIByteString
147133
148−-- | This attempts to provide the most common HTTP status codes, not all of
149−-- them. Use the Status constructor when you want to create a status code not
150−-- provided.
151−--
152−-- The 'Eq' instance tests equality based only on the numeric status code
153−-- value. See 'statusCode'.
134+-- | HTTP status code; a combination of the integral code and a status message.
135+-- Equality is determined solely on the basis of the integral code.
154136data Status = Status { statusCode :: Int, statusMessage :: B.ByteString }
155137 deriving Show
156138
157139instance Eq Status where
158140 x == y = statusCode x == statusCode y
159141
142+-- | OK
160143status200 :: Status
161144status200 = Status 200 $ B8.pack "OK"
162145
146+-- | Moved Permanently
163147status301 :: Status
164148status301 = Status 301 $ B8.pack "Moved Permanently"
165149
150+-- | Found
166151status302 :: Status
167152status302 = Status 302 $ B8.pack "Found"
168153
154+-- | See Other
169155status303 :: Status
170156status303 = Status 303 $ B8.pack "See Other"
171157
158+-- | Bad Request
172159status400 :: Status
173160status400 = Status 400 $ B8.pack "Bad Request"
174161
162+-- | Unauthorized
175163status401 :: Status
176164status401 = Status 401 $ B8.pack "Unauthorized"
177165
166+-- | Forbidden
178167status403 :: Status
179168status403 = Status 403 $ B8.pack "Forbidden"
180169
170+-- | Not Found
181171status404 :: Status
182172status404 = Status 404 $ B8.pack "Not Found"
183173
174+-- | Method Not Allowed
184175status405 :: Status
185176status405 = Status 405 $ B8.pack "Method Not Allowed"
186177
178+-- | Internal Server Error
187179status500 :: Status
188180status500 = Status 500 $ B8.pack "Internal Server Error"
189181
@@ -194,6 +186,12 @@ status500 = Status 500 $ B8.pack "Internal Server Error"
194186--
195187-- Be certain not to reuse a 'Source'! It might work fine with some
196188-- implementations of 'Source', while causing bugs with others.
189+--
190+-- This datatype is used by WAI to represent a request body. We choose this
191+-- over an enumerator in that it gives the application power over control flow.
192+-- This not only makes it easier to use in many situations, but also allows
193+-- implementation of some features such as a backtracking parser which doesn't
194+-- read the entire body into memory.
197195newtype Source = Source { runSource :: IO (Maybe (B.ByteString, Source)) }
198196
199197-- | An enumerator is a data producer. It takes two arguments: a function to
@@ -225,6 +223,10 @@ newtype Source = Source { runSource :: IO (Maybe (B.ByteString, Source)) }
225223-- 'Enumerator' may only be called once. While this requirement puts a bit of a
226224-- strain on the caller in some situations, it saves a large amount of
227225-- complication- and thus performance- on the producer.
226+--
227+-- In WAI, an Enumerator is used to represent the response body. We have
228+-- specifically chosen one of the simplest representations of an enumerator to
229+-- avoid coding complication and performance overhead.
228230newtype Enumerator = Enumerator { runEnumerator :: forall a.
229231 (a -> B.ByteString -> IO (Either a a))
230232 -> a
@@ -246,13 +248,29 @@ data Request = Request
246248 , serverName :: B.ByteString
247249 , serverPort :: Int
248250 , requestHeaders :: [(RequestHeader, B.ByteString)]
251+ -- ^ Was this request made over an SSL connection?
249252 , isSecure :: Bool
250253 , requestBody :: Source
254+ -- ^ Log the given line in some method; how this is accomplished is
255+ -- server-dependant.
251256 , errorHandler :: String -> IO ()
252257 -- | The client\'s host information.
253258 , remoteHost :: B.ByteString
254259 }
255260
261+-- | The response body returned to the server from the application. We provide
262+-- three separate constructors as optimizations:
263+--
264+-- * 'ResponseEnumerator' is the most general type, allowing constant-memory
265+-- production of a response, even in the presence of interleaved I\/O actions.
266+--
267+-- * 'ResponseFile' serves a static file from the filesystem. Many servers use
268+-- a sendfile system call to optimize this type of serving, making this a huge
269+-- performance gain.
270+--
271+-- * 'ResponseLBS'. Often times, we wish to return a response that includes no
272+-- interleaved I\/O. In this case, we can use Haskell's natural laziness to our
273+-- advantage, and represent the response as a lazy bytestring.
256274data ResponseBody = ResponseFile FilePath
257275 | ResponseEnumerator Enumerator
258276 | ResponseLBS L.ByteString