packages feed

wai 1.4.1 → 2.0.0

raw patch · 3 files changed

+244/−111 lines, 3 filesdep ~conduit

Dependency ranges changed: conduit

Files

Network/Wai.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE Rank2Types #-} {-# LANGUAGE CPP #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE DeriveDataTypeable #-} {-|  This module defines a generic web application interface. It is a common@@ -37,89 +35,69 @@  -} module Network.Wai-    ( -- * WAI interface-      Request (..)-    , Response (..)-    , responseSource-    , Application+    (+      -- * Ttypes+      Application     , Middleware-    , FilePart (..)+      -- * Request+    , Request+    , defaultRequest     , RequestBodyLength (..)+      -- ** Request accessors+    , requestMethod+    , httpVersion+    , rawPathInfo+    , rawQueryString+    , requestHeaders+    , isSecure+    , remoteHost+    , pathInfo+    , queryString+    , requestBody+    , vault+    , requestBodyLength+    , requestHeaderHost+    , requestHeaderRange     , lazyRequestBody-      -- * Response body smart constructors+      -- * Response+    , Response+    , FilePart (..)+    , WithSource+      -- ** Response composers+    , responseFile+    , responseBuilder     , responseLBS+    , responseSource+    , responseSourceBracket+      -- * Response accessors     , responseStatus+    , responseHeaders+    , responseToSource     ) where -import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as L-import Data.Typeable (Typeable)-import qualified Data.Conduit as C-import qualified Data.Conduit.List as CL-import Data.Conduit.Lazy (lazyConsume)-import qualified Data.Conduit.Binary as CB-import Blaze.ByteString.Builder (Builder, fromLazyByteString)-import Network.Socket (SockAddr)-import qualified Network.HTTP.Types as H-import Data.Text (Text)-import Data.ByteString.Lazy.Char8 () -- makes it easier to use responseLBS-import Blaze.ByteString.Builder (fromByteString)-#if MIN_VERSION_vault(0,3,0)-import Data.Vault.Lazy (Vault)-#else-import Data.Vault (Vault)-#endif-import Data.Word (Word64)+import           Blaze.ByteString.Builder     (Builder, fromLazyByteString)+import           Blaze.ByteString.Builder     (fromByteString)+import           Control.Exception            (bracket, bracketOnError)+import qualified Data.ByteString              as B+import qualified Data.ByteString.Lazy         as L+import           Data.ByteString.Lazy.Char8   ()+import qualified Data.Conduit                 as C+import qualified Data.Conduit.Binary          as CB+import           Data.Conduit.Lazy            (lazyConsume)+import qualified Data.Conduit.List            as CL+import           Data.Monoid                  (mempty)+import qualified Network.HTTP.Types           as H+import           Network.Socket               (SockAddr (SockAddrInet))+import           Network.Wai.Internal+import qualified System.IO                    as IO --- | Information on the request sent by the client. This abstracts away the--- details of the underlying implementation.-data Request = Request-  {  requestMethod  :: H.Method-  ,  httpVersion    :: H.HttpVersion-  -- | Extra path information sent by the client. The meaning varies slightly-  -- depending on backend; in a standalone server setting, this is most likely-  -- all information after the domain name. In a CGI application, this would be-  -- the information following the path to the CGI executable itself.-  -- Do not modify this raw value- modify pathInfo instead.-  ,  rawPathInfo    :: B.ByteString-  -- | If no query string was specified, this should be empty. This value-  -- /will/ include the leading question mark.-  -- Do not modify this raw value- modify queryString instead.-  ,  rawQueryString :: B.ByteString-  -- | Generally the host requested by the user via the Host request header.-  -- Backends are free to provide alternative values as necessary. This value-  -- should not be used to construct URLs.-  ,  serverName     :: B.ByteString-  -- | The listening port that the server received this request on. It is-  -- possible for a server to listen on a non-numeric port (i.e., Unix named-  -- socket), in which case this value will be arbitrary. Like 'serverName',-  -- this value should not be used in URL construction.-  ,  serverPort     :: Int-  ,  requestHeaders :: H.RequestHeaders-  -- | Was this request made over an SSL connection?-  ---  -- This value should /not/ be used, and will be removed in future revisions-  -- of WAI. There is no meaningful way that a backend can indicate whether the-  -- request is actually over a secure channel, due to issues of reverse-  -- proxying.-  ,  isSecure       :: Bool-  -- | The client\'s host information.-  ,  remoteHost     :: SockAddr-  -- | Path info in individual pieces- the url without a hostname/port and without a query string, split on forward slashes,-  ,  pathInfo       :: [Text]-  -- | Parsed query string information-  ,  queryString    :: H.Query-  ,  requestBody    :: C.Source (C.ResourceT IO) B.ByteString-  -- | A location for arbitrary data to be shared by applications and middleware.-  , vault           :: Vault-  -- | The size of the request body. In the case of a chunked request body, this may be unknown.-  ---  -- Since 1.4.0-  , requestBodyLength :: RequestBodyLength-  }-  deriving (Typeable)+---------------------------------------------------------------- --- |+-- | Creating 'Response' from a file.+responseFile :: H.Status -> H.ResponseHeaders -> FilePath -> Maybe FilePart -> Response+responseFile = ResponseFile++-- | Creating 'Response' from 'Builder'. -- -- Some questions and answers about the usage of 'Builder' here: --@@ -142,41 +120,72 @@ -- -- A3. You can force blaze-builder to output a ByteString before it is an -- optimal size by sending a flush command.-data Response-    = ResponseFile H.Status H.ResponseHeaders FilePath (Maybe FilePart)-    | ResponseBuilder H.Status H.ResponseHeaders Builder-    | ResponseSource H.Status H.ResponseHeaders (C.Source (C.ResourceT IO) (C.Flush Builder))-  deriving Typeable+responseBuilder :: H.Status -> H.ResponseHeaders -> Builder -> Response+responseBuilder = ResponseBuilder +-- | Creating 'Response' from 'L.ByteString'. This is a wrapper for+--   'responseBuilder'.+responseLBS :: H.Status -> H.ResponseHeaders -> L.ByteString -> Response+responseLBS s h = ResponseBuilder s h . fromLazyByteString++-- | Creating 'Response' from 'C.Source'.+responseSource :: H.Status -> H.ResponseHeaders -> C.Source IO (C.Flush Builder) -> Response+responseSource st hs src = ResponseSource st hs ($ src)++-- | Creating 'Response' with allocated resource safely released.+--+--   * The first argument is an action to allocate resource.+--+--   * The second argument is a function to release the resource.+--+--   * The third argument is a function to create+--     ('H.Status','H.ResponseHeaders','C.Source' 'IO' ('C.Flush' 'Builder'))+--     from the resource.+responseSourceBracket :: IO a+                      -> (a -> IO ())+                      -> (a -> IO (H.Status+                                  ,H.ResponseHeaders+                                  ,C.Source IO (C.Flush Builder)))+                      -> IO Response+responseSourceBracket setup teardown action =+    bracketOnError setup teardown $ \resource -> do+        (st,hdr,src) <- action resource+        return $ ResponseSource st hdr $ \f ->+            bracket (return resource) teardown (\_ -> f src)++----------------------------------------------------------------++-- | Accessing 'H.Status' in 'Response'. responseStatus :: Response -> H.Status-responseStatus rsp =-    case rsp of-      ResponseFile    s _ _ _ -> s-      ResponseBuilder s _ _   -> s-      ResponseSource  s _ _   -> s+responseStatus (ResponseFile    s _ _ _) = s+responseStatus (ResponseBuilder s _ _  ) = s+responseStatus (ResponseSource  s _ _  ) = s -data FilePart = FilePart-    { filePartOffset :: Integer-    , filePartByteCount :: Integer-    } deriving Show+-- | Accessing 'H.Status' in 'Response'.+responseHeaders :: Response -> H.ResponseHeaders+responseHeaders (ResponseFile    _ hs _ _) = hs+responseHeaders (ResponseBuilder _ hs _  ) = hs+responseHeaders (ResponseSource  _ hs _  ) = hs -responseSource :: Response -> (H.Status, H.ResponseHeaders, C.Source (C.ResourceT IO) (C.Flush Builder))-responseSource (ResponseSource s h b) = (s, h, b)-responseSource (ResponseFile s h fp (Just part)) =-    (s, h, sourceFilePart part fp C.$= CL.map (C.Chunk . fromByteString))-responseSource (ResponseFile s h fp Nothing) =-    (s, h, CB.sourceFile fp C.$= CL.map (C.Chunk . fromByteString))-responseSource (ResponseBuilder s h b) =-    (s, h, CL.sourceList [C.Chunk b])+-- | Converting the body information in 'Response' to 'Source'.+responseToSource :: Response+                 -> (H.Status, H.ResponseHeaders, WithSource IO (C.Flush Builder) b)+responseToSource (ResponseSource s h b) = (s, h, b)+responseToSource (ResponseFile s h fp (Just part)) =+    (s, h, \f -> IO.withFile fp IO.ReadMode $ \handle -> f $ sourceFilePart handle part C.$= CL.map (C.Chunk . fromByteString))+responseToSource (ResponseFile s h fp Nothing) =+    (s, h, \f -> IO.withFile fp IO.ReadMode $ \handle -> f $ CB.sourceHandle handle C.$= CL.map (C.Chunk . fromByteString))+responseToSource (ResponseBuilder s h b) =+    (s, h, ($ CL.sourceList [C.Chunk b])) -sourceFilePart :: C.MonadResource m => FilePart -> FilePath -> C.Source m B.ByteString-sourceFilePart (FilePart offset count) fp =-    CB.sourceFileRange fp (Just offset) (Just count)+sourceFilePart :: IO.Handle -> FilePart -> C.Source IO B.ByteString+sourceFilePart handle (FilePart offset count _) =+    CB.sourceHandleRange handle (Just offset) (Just count) -responseLBS :: H.Status -> H.ResponseHeaders -> L.ByteString -> Response-responseLBS s h = ResponseBuilder s h . fromLazyByteString+---------------------------------------------------------------- -type Application = Request -> C.ResourceT IO Response+-- | The WAI application.+type Application = Request -> IO Response  -- | 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@@ -194,15 +203,30 @@ -- middleware takes a function which consumes the session information as well. type Middleware = Application -> Application --- | The size of the request body. In the case of chunked bodies, the size will--- not be known.+-- | A default, blank request. ----- Since 1.4.0-data RequestBodyLength = ChunkedBody | KnownLength Word64+-- Since 2.0.0+defaultRequest :: Request+defaultRequest = Request+    { requestMethod = H.methodGet+    , httpVersion = H.http10+    , rawPathInfo = B.empty+    , rawQueryString = B.empty+    , requestHeaders = []+    , isSecure = False+    , remoteHost = SockAddrInet 0 0+    , pathInfo = []+    , queryString = []+    , requestBody = return ()+    , vault = mempty+    , requestBodyLength = KnownLength 0+    , requestHeaderHost = Nothing+    , requestHeaderRange = Nothing+    }  -- | Get the request body as a lazy ByteString. This uses lazy I\/O under the -- surface, and therefore all typical warnings regarding lazy I/O apply. -- -- Since 1.4.1-lazyRequestBody :: Request -> C.ResourceT IO L.ByteString+lazyRequestBody :: Request -> IO L.ByteString lazyRequestBody = fmap L.fromChunks . lazyConsume . requestBody
+ Network/Wai/Internal.hs view
@@ -0,0 +1,108 @@+{-# OPTIONS_HADDOCK not-home #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE RankNTypes #-}+-- | Internal constructors and helper functions. Note that no guarantees are+-- given for stability of these interfaces.+module Network.Wai.Internal where++import           Blaze.ByteString.Builder     (Builder)+import qualified Data.ByteString              as B+import qualified Data.Conduit                 as C+import           Data.Text                    (Text)+import           Data.Typeable                (Typeable)+#if MIN_VERSION_vault(0,3,0)+import Data.Vault.Lazy (Vault)+#else+import Data.Vault (Vault)+#endif+import           Data.Word                    (Word64)+import qualified Network.HTTP.Types           as H+import           Network.Socket               (SockAddr)++-- | Information on the request sent by the client. This abstracts away the+-- details of the underlying implementation.+data Request = Request {+  -- | Request method such as GET.+     requestMethod        :: H.Method+  -- | HTTP version such as 1.1.+  ,  httpVersion          :: H.HttpVersion+  -- | Extra path information sent by the client. The meaning varies slightly+  -- depending on backend; in a standalone server setting, this is most likely+  -- all information after the domain name. In a CGI application, this would be+  -- the information following the path to the CGI executable itself.+  -- Do not modify this raw value- modify pathInfo instead.+  ,  rawPathInfo          :: B.ByteString+  -- | If no query string was specified, this should be empty. This value+  -- /will/ include the leading question mark.+  -- Do not modify this raw value- modify queryString instead.+  ,  rawQueryString       :: B.ByteString+  -- | A list of header (a pair of key and value) in an HTTP request.+  ,  requestHeaders       :: H.RequestHeaders+  -- | Was this request made over an SSL connection?+  --+  -- Note that this value will /not/ tell you if the client originally made+  -- this request over SSL, but rather whether the current connection is SSL.+  -- The distinction lies with reverse proxies. In many cases, the client will+  -- connect to a load balancer over SSL, but connect to the WAI handler+  -- without SSL. In such a case, @isSecure@ will be @False@, but from a user+  -- perspective, there is a secure connection.+  ,  isSecure             :: Bool+  -- | The client\'s host information.+  ,  remoteHost           :: SockAddr+  -- | Path info in individual pieces- the url without a hostname/port and without a query string, split on forward slashes,+  ,  pathInfo             :: [Text]+  -- | Parsed query string information+  ,  queryString          :: H.Query+  -- | A request body provided as 'Source'.+  ,  requestBody          :: C.Source IO B.ByteString+  -- | A location for arbitrary data to be shared by applications and middleware.+  , vault                 :: Vault+  -- | The size of the request body. In the case of a chunked request body, this may be unknown.+  --+  -- Since 1.4.0+  , requestBodyLength     :: RequestBodyLength+  -- | The value of the Host header in a HTTP request.+  --+  -- Since 2.0.0+  , requestHeaderHost     :: Maybe B.ByteString+  -- | The value of the Range header in a HTTP request.+  --+  -- Since 2.0.0+  , requestHeaderRange   :: Maybe B.ByteString+  }+  deriving (Typeable)++-- | The strange structure of the third field or ResponseSource is to allow for+-- exception-safe resource allocation. As an example:+--+-- > app :: Application+-- > app _ = return $ ResponseSource status200 [] $ \f -> bracket+-- >     (putStrLn "Allocation" >> return 5)+-- >     (\i -> putStrLn $ "Cleaning up: " ++ show i)+-- >     (\_ -> f $ do+-- >         yield $ Chunk $ fromByteString "Hello "+-- >         yield $ Chunk $ fromByteString "World!")+data Response+    = ResponseFile H.Status H.ResponseHeaders FilePath (Maybe FilePart)+    | ResponseBuilder H.Status H.ResponseHeaders Builder+    | ResponseSource H.Status H.ResponseHeaders (forall b. WithSource IO (C.Flush Builder) b)+  deriving Typeable++-- | Auxiliary type for 'ResponseSource'.+type WithSource m a b = (C.Source m a -> m b) -> m b++-- | The size of the request body. In the case of chunked bodies, the size will+-- not be known.+--+-- Since 1.4.0+data RequestBodyLength = ChunkedBody | KnownLength Word64++-- | Information on which part to be sent.+--   Sophisticated application handles Range (and If-Range) then+--   create 'FilePart'.+data FilePart = FilePart+    { filePartOffset    :: Integer+    , filePartByteCount :: Integer+    , filePartFileSize  :: Integer+    } deriving Show
wai.cabal view
@@ -1,5 +1,5 @@ Name:                wai-Version:             1.4.1+Version:             2.0.0 Synopsis:            Web Application Interface. Description:         Provides a common protocol for communication between web applications and web servers. License:             MIT@@ -20,11 +20,12 @@   Build-Depends:     base                      >= 4        && < 5                    , bytestring                >= 0.9.1.4                    , blaze-builder             >= 0.2.1.4  && < 0.4-                   , conduit                   >= 0.5      && < 1.1+                   , conduit                   >= 1.0.8    && < 1.1                    , network                   >= 2.2.1.5                    , http-types                >= 0.7                    , text                      >= 0.7                    , transformers              >= 0.2.2                    , vault                     >= 0.1      && < 0.4   Exposed-modules:   Network.Wai+                     Network.Wai.Internal   ghc-options:       -Wall