on master help sign in
Updated documentation
commit480122b58097f0bcf93ec208d959ff3be8b55288 authorSnoyman <snoyman@snoytop-karmic.(none)> dateFri 26 Feb 2010, 15:04 (17 years ago) parent062d1b9
3 files changed+46−17
Network/Wai.hs+27−15 Network/Wai/Enumerator.hs+11−1 Network/Wai/Source.hs+8−1
Network/Wai.hs+27−15
@@ -6,20 +6,20 @@ This module defines a generic web application interface. It is a common
66protocol between web servers and web applications.
77
88The overriding design principles here are performance, generality and type
9−safety. To address performance, this library is built on 'Enumerator's for the
10−request and response bodies. The advantages of this approach over lazy IO has
11−been debated elsewhere.
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.
1212
13−Nonetheless, many people find 'Enumerator's difficult to work with. For that
14−reason, this library includes the "Network.Wai.Enumerator" module to provide
15−more familiar abstractions, including lazy IO.
13+Nonetheless, many people find these data structures difficult to work with. For
14+that reason, this library includes the "Network.Wai.Enumerator" module to
15+provide more familiar abstractions, including lazy IO.
1616
1717Generality 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
2121Unlike other approaches, this package declares many data types to assist in
22−type safety. This feels more in the general Haskell spirit.
22+type safety. This feels more inline with the general Haskell spirit.
2323
2424A final note: please remember when using this package that, while your
2525application my compile without a hitch against many different servers, there
@@ -56,8 +56,9 @@ module Network.Wai
5656 , Status (..)
5757 , statusCode
5858 , statusMessage
59− -- * Enumerator
59+ -- ** Source
6060 , Source (..)
61+ -- * Enumerator
6162 , Enumerator (..)
6263 -- * WAI interface
6364 , Request (..)
@@ -310,6 +311,18 @@ statusMessage Status405 = B8.pack "Method Not Allowed"
310311statusMessage Status500 = B8.pack "Internal Server Error"
311312statusMessage (Status _ m) = m
312313
314+-- | This is a source for 'B.ByteString's. It is composed of two pieces: a
315+-- state variable, and a function to produce the output. The type of the state
316+-- variable is completely unknown to the user; some examples might be an 'Int'
317+-- for the remaining length of the content, or a list of 'B.ByteString's from
318+-- which to generate content.
319+--
320+-- The function accepts that state variable as its first argument. If input has
321+-- been fully consumed, it returns 'Nothing'; otherwise, it returns the next
322+-- piece of data and the next state.
323+--
324+-- Be certain not to reuse a state variable! It might work fine with some
325+-- implementations of 'Source', while causing bugs with others.
313326data Source = forall a. Source a (a -> IO (Maybe (B.ByteString, a)))
314327
315328-- | An enumerator is a data producer. It takes two arguments: a function to
@@ -337,10 +350,6 @@ data Source = forall a. Source a (a -> IO (Maybe (B.ByteString, a)))
337350-- 'Either' value; a 'Right' means the enumerator ran to completion, while a
338351-- 'Left' indicates early termination was requested by the iteratee.
339352--
340−-- 'Enumerator's are used twice in the WAI: once in the 'Request' datatype to
341−-- access the request body, and once in the 'Response' datatype for the
342−-- application to return the body of the response.
343−--
344353-- 'Enumerator's are not required to be resumable. That is to say, the
345354-- 'Enumerator' may only be called once. While this requirement puts a bit of a
346355-- strain on the caller in some situations, it saves a large amount of
@@ -378,14 +387,17 @@ data Response = Response
378387 , responseHeaders :: [(ResponseHeader, B.ByteString)]
379388 -- | A common optimization is to use the sendfile system call when sending
380389 -- files from the disk. This datatype facilitates this optimization; if
381− -- 'Left' is returns, the server will send the file from the disk by whatever
382− -- means it wishes. If 'Right', it will call the 'Enumerator'.
390+ -- 'Left' is returned, the server will send the file from the disk by
391+ -- whatever means it wishes. If 'Right', it will call the 'Enumerator'.
383392 , responseBody :: Either FilePath Enumerator
384393 }
385394
386395type Application = Request -> IO Response
387396
388−-- | Middleware is a component that sits between the server and application. It can do such tasks as GZIP encoding or response caching. What follows is the general definition of middleware, though a middleware author should feel free to modify this.
397+-- | Middleware is a component that sits between the server and application. It
398+-- can do such tasks as GZIP encoding or response caching. What follows is the
399+-- general definition of middleware, though a middleware author should feel
400+-- free to modify this.
389401--
390402-- As an example of an alternate type for middleware, suppose you write a
391403-- function to load up session information. The session information is simply a
Network/Wai/Enumerator.hs+11−1
@@ -34,7 +34,8 @@ mapE f (Enumerator e) = Enumerator $ \iter -> e (iter' iter) where
3434 iter' iter a = iter a . f
3535
3636-- | This uses 'unsafeInterleaveIO' to lazily read from an enumerator. All
37−-- normal lazy I/O warnings apply.
37+-- normal lazy I/O warnings apply. In addition, since it is based on
38+-- 'toSource', please observe all precautions for that function.
3839toLBS :: Enumerator -> IO L.ByteString
3940toLBS = Source.toLBS <=< toSource
4041
@@ -55,6 +56,15 @@ fromLBS' :: IO L.ByteString -> Enumerator
5556fromLBS' lbs' = Enumerator $ \iter a0 -> lbs' >>= \lbs ->
5657 runEnumerator (fromLBS lbs) iter a0
5758
59+-- | This function uses another thread to convert an 'Enumerator' to a
60+-- 'Source'. In essence, this allows you to write code which \"pulls\" instead
61+-- of code which is pushed to. While this can be a useful technique, some
62+-- caveats apply:
63+--
64+-- * It will be more resource heavy than using the 'Enumerator' directly.
65+--
66+-- * You *must* consume all input. If you do not, then the other thread will be
67+-- deadlocked.
5868toSource :: Enumerator -> IO Source
5969toSource (Enumerator e) = do
6070 buffer <- newEmptyMVar
Network/Wai/Source.hs+8−1
@@ -1,5 +1,7 @@
11module Network.Wai.Source
2− ( toEnumerator
2+ (
3+ -- * Conversions
4+ toEnumerator
35 , toLBS
46 ) where
57
@@ -7,6 +9,9 @@ import Network.Wai
79import qualified Data.ByteString.Lazy as L
810import System.IO.Unsafe (unsafeInterleaveIO)
911
12+-- | This function safely converts a 'Source' (where you pull data) to an
13+-- 'Enumerator' (which pushes the data to you). There should be no significant
14+-- performance impact from its use, and it uses no unsafe functions.
1015toEnumerator :: Source -> Enumerator
1116toEnumerator (Source b0 source) = Enumerator $ helper b0 where
1217 helper b iter a = do
@@ -19,6 +24,8 @@ toEnumerator (Source b0 source) = Enumerator $ helper b0 where
1924 Left a' -> return $ Left a'
2025 Right a' -> helper b' iter a'
2126
27+-- | Uses lazy I\/O (via 'unsafeInterleaveIO') to provide a lazy interface to
28+-- the given 'Source'. Normal lazy I\/O warnings apply.
2229toLBS :: Source -> IO L.ByteString
2330toLBS (Source b0 source) = L.fromChunks `fmap` helper b0 where
2431 helper b = unsafeInterleaveIO $ do