]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
Doc fix, optimization, and more.
authorpho <pho@cielonegro.org>
Wed, 3 Oct 2007 16:17:37 +0000 (01:17 +0900)
committerpho <pho@cielonegro.org>
Wed, 3 Oct 2007 16:17:37 +0000 (01:17 +0900)
darcs-hash:20071003161737-62b54-4bf7a3e6c3df2756007e22d5c4978be9ae7faa17.gz

12 files changed:
ImplantFile.hs
Network/HTTP/Lucu/Abortion.hs
Network/HTTP/Lucu/DefaultPage.hs
Network/HTTP/Lucu/Parser.hs
Network/HTTP/Lucu/Parser/Http.hs
Network/HTTP/Lucu/RFC1123DateTime.hs
Network/HTTP/Lucu/Resource.hs
Network/HTTP/Lucu/Resource.hs-boot [deleted file]
Network/HTTP/Lucu/Resource/Tree.hs
Network/HTTP/Lucu/Response.hs
Network/HTTP/Lucu/StaticFile.hs
Network/HTTP/Lucu/Utils.hs

index 29c11450deab634a6a0c3c0b5d72637f51fecb92..a16c76ec8bee3eb9331cdf9c42a24b99facd99ec 100644 (file)
@@ -2,7 +2,7 @@ import           Codec.Binary.Base64
 import           Codec.Compression.GZip
 import           Control.Monad
 import           Data.Bits
-import           Data.ByteString.Lazy (ByteString)
+import           Data.ByteString.Base (LazyByteString)
 import qualified Data.ByteString.Lazy as L
 import           Data.Char
 import           Data.Digest.SHA1
@@ -117,8 +117,8 @@ generateHaskellSource opts srcFile
              exports  = [HsEVar (UnQual (HsIdent symName))]
              imports  = [ HsImportDecl undefined (Module "Codec.Binary.Base64")
                                        False Nothing Nothing
-                        , HsImportDecl undefined (Module "Data.ByteString.Lazy")
-                                       False Nothing (Just (False, [HsIVar (HsIdent "ByteString")]))
+                        , HsImportDecl undefined (Module "Data.ByteString.Base")
+                                       False Nothing (Just (False, [HsIVar (HsIdent "LazyByteString")]))
                         , HsImportDecl undefined (Module "Data.ByteString.Lazy")
                                        True (Just (Module "L")) Nothing
                         , HsImportDecl undefined (Module "Network.HTTP.Lucu")
@@ -207,7 +207,7 @@ generateHaskellSource opts srcFile
                                    expOutputGunzipped
                                    expOutputGZipped)
                        expOutputGunzipped
-                           = (HsApp (HsVar (UnQual (HsIdent "outputBS")))
+                           = (HsApp (HsVar (UnQual (HsIdent "outputLBS")))
                               (HsParen
                                (HsApp (HsVar (UnQual (HsIdent "decompress")))
                                       (HsVar (UnQual (HsIdent "gzippedData"))))))
@@ -219,7 +219,7 @@ generateHaskellSource opts srcFile
                            = HsQualifier (HsApp (HsVar (UnQual (HsIdent "setContentEncoding")))
                                           (HsList [HsLit (HsString "gzip")]))
                        doOutputGZipped
-                           = HsQualifier (HsApp (HsVar (UnQual (HsIdent "outputBS")))
+                           = HsQualifier (HsApp (HsVar (UnQual (HsIdent "outputLBS")))
                                           (HsVar (UnQual (HsIdent "gzippedData"))))
                    in 
                      HsApp (HsCon (UnQual (HsIdent "Just")))
@@ -239,7 +239,7 @@ generateHaskellSource opts srcFile
                            = HsQualifier (HsApp (HsVar (UnQual (HsIdent "setContentType")))
                                           (HsVar (UnQual (HsIdent "contentType"))))
                        doOutputRawData
-                           = HsQualifier (HsApp (HsVar (UnQual (HsIdent "outputBS")))
+                           = HsQualifier (HsApp (HsVar (UnQual (HsIdent "outputLBS")))
                                           (HsVar (UnQual (HsIdent "rawData"))))
                    in
                      HsApp (HsCon (UnQual (HsIdent "Just")))
@@ -295,7 +295,7 @@ generateHaskellSource opts srcFile
              declGZippedData 
                  = [ HsTypeSig undefined [HsIdent "gzippedData"]
                                (HsQualType []
-                                (HsTyCon (UnQual (HsIdent "ByteString"))))
+                                (HsTyCon (UnQual (HsIdent "LazyByteString"))))
                    , HsFunBind [HsMatch undefined (HsIdent "gzippedData")
                                 [] (HsUnGuardedRhs defGZippedData) []]
                    ]
@@ -311,7 +311,7 @@ generateHaskellSource opts srcFile
              declRawData 
                  = [ HsTypeSig undefined [HsIdent "rawData"]
                                (HsQualType []
-                                (HsTyCon (UnQual (HsIdent "ByteString"))))
+                                (HsTyCon (UnQual (HsIdent "LazyByteString"))))
                    , HsFunBind [HsMatch undefined (HsIdent "rawData")
                                 [] (HsUnGuardedRhs defRawData) []]
                    ]
@@ -397,7 +397,7 @@ getLastModified "-"   = getClockTime
 getLastModified fpath = getModificationTime fpath
 
 
-getETag :: [CmdOpt] -> ByteString -> IO String
+getETag :: [CmdOpt] -> LazyByteString -> IO String
 getETag opts input
     = let eTagOpts = filter (\ x -> case x of
                                       OptETag _ -> True
@@ -425,7 +425,7 @@ getETag opts input
           | n < 16 = (chr $ ord 'a' + n - 10)
 
 
-openInput :: FilePath -> IO ByteString
+openInput :: FilePath -> IO LazyByteString
 openInput "-"   = L.getContents
 openInput fpath = L.readFile fpath
 
@@ -458,7 +458,7 @@ openOutput opts
    -}
   module Foo.Bar.Baz (baz) where
   import Codec.Binary.Base64
-  import Data.ByteString.Lazy (ByteString)
+  import Data.ByteString.Base (LazyByteString)
   import qualified Data.ByteString.Lazy as L
   import Network.HTTP.Lucu
   import System.Time
@@ -470,7 +470,7 @@ openOutput opts
         , resGet
             = Just (do foundEntity entityTag lastModified
                        setContentType contentType
-                       outputBS rawData)
+                       outputLBS rawData)
         , resHead   = Nothing
         , resPost   = Nothing
         , resPut    = Nothing
@@ -486,7 +486,7 @@ openOutput opts
   contentType :: MIMEType
   contentType = read "image/png"
 
-  rawData :: ByteString
+  rawData :: LazyByteString
   rawData = L.pack (decode "IyEvdXNyL2Jpbi9lbnYgcnVuZ2hjCgppbXBvcnQgRGlzdHJ...")
   ------------------------------------------------------------------------------
 
@@ -507,10 +507,10 @@ openOutput opts
 
                        mustGunzip <- liftM not (isEncodingAcceptable "gzip")
                        if mustGunzip then
-                           outputBS (decompress gzippedData)
+                           outputLBS (decompress gzippedData)
                          else
                            do setContentEncoding ["gzip"]
-                              outputBS gzippedData
+                              outputLBS gzippedData
         , resHead   = Nothing
         , resPost   = Nothing
         , resPut    = Nothing
@@ -518,7 +518,7 @@ openOutput opts
         }
   
   -- rawData の代はりに gzippedData
-  gzippedData :: ByteString
+  gzippedData :: LazyByteString
   gzippedData = L.pack (decode "Otb/+DniOlRgAAAAYAAAAGAAAAB/6QOmToAEIGAAAAB...")
   ------------------------------------------------------------------------------
  -}
index ef704771a7f0164950b52f83700ec9849db49cfd..9ff629df73e84db0eac2a50073e06b2494eb120b 100644 (file)
@@ -23,7 +23,6 @@ import           Network.HTTP.Lucu.DefaultPage
 import           Network.HTTP.Lucu.Headers
 import           Network.HTTP.Lucu.Request
 import           Network.HTTP.Lucu.Response
-import {-# SOURCE #-} Network.HTTP.Lucu.Resource
 import           System.IO.Unsafe
 import           Text.XML.HXT.Arrow.WriteDocument
 import           Text.XML.HXT.Arrow.XmlArrow
@@ -68,7 +67,6 @@ abort status headers msg
           exc = DynException (toDyn abo)
       in
         liftIO $ throwIO exc
-{-# SPECIALIZE abort :: StatusCode -> [ (String, String) ] -> Maybe String -> Resource a #-}
 
 -- |Computation of @'abortSTM' status headers msg@ just computes
 -- 'abort' in a 'Control.Monad.STM.STM' monad.
@@ -82,7 +80,6 @@ abortSTM status headers msg
 abortA :: ArrowIO a => a (StatusCode, ([ (String, String) ], Maybe String)) c
 abortA 
     = arrIO3 abort
-{-# SPECIALIZE abortA :: IOSArrow (StatusCode, ([ (String, String) ], Maybe String)) c #-}
 
 -- aboMessage が Just なら單に mkDefaultPage に渡すだけで良いので樂だが、
 -- Nothing の場合は getDefaultPage を使ってデフォルトのメッセージを得な
index 05acb60e5162711c840069aac3ab41a4aebd69de..b4413ce96b1a7017399bc65a9893b1a2b3954da6 100644 (file)
@@ -60,15 +60,15 @@ writeDefaultPage itr
 mkDefaultPage :: (ArrowXml a) => Config -> StatusCode -> a b XmlTree -> a b XmlTree
 mkDefaultPage conf status msgA
     = conf `seq` status `seq` msgA `seq`
-      let (sCode, sMsg) = statusCode status
-          sig           = cnfServerSoftware conf
-                          ++ " at "
-                          ++ cnfServerHost conf
-                          ++ ( case cnfServerPort conf of
-                                 Service    serv -> ", service " ++ serv
-                                 PortNumber num  -> ", port " ++ show num
-                                 UnixSocket path -> ", unix socket " ++ show path
-                             )
+      let (# sCode, sMsg #) = statusCode status
+          sig               = cnfServerSoftware conf
+                              ++ " at "
+                              ++ cnfServerHost conf
+                              ++ ( case cnfServerPort conf of
+                                     Service    serv -> ", service " ++ serv
+                                     PortNumber num  -> ", port " ++ show num
+                                     UnixSocket path -> ", unix socket " ++ show path
+                                 )
       in ( eelem "/"
            += ( eelem "html"
                 += sattr "xmlns" "http://www.w3.org/1999/xhtml"
index 5671ec0ccdf8c1c505a9bdf20cd227d8b1e07ec0..c40cacd0d4c17521817c7e3e8d2fb6c79394731d 100644 (file)
@@ -93,8 +93,8 @@ instance Monad Parser where
 failP :: Parser a
 failP = fail undefined
 
--- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(result,
--- remaining)@.
+-- |@'parse' p bstr@ parses @bstr@ with @p@ and returns @(result,
+-- remaining #)@.
 parse :: Parser a -> LazyByteString -> (# ParserResult a, LazyByteString #)
 parse p input -- input は lazy である必要有り。
     = p `seq`
index 77dbe7f225bb2b6c3950b497815efa077d6c98b2..a5dfbd90677853038f2a3ee10e8799f3978adf91 100644 (file)
@@ -20,14 +20,15 @@ module Network.HTTP.Lucu.Parser.Http
 import           Data.List
 import           Network.HTTP.Lucu.Parser
 
--- |@'isCtl' c@ is False iff @0x20 <= @c@ < 0x7F@.
+-- |@'isCtl' c@ is 'Prelude.False' iff @0x20 <= @c@ < 0x7F@.
 isCtl :: Char -> Bool
 isCtl c
     | c <  '\x1f' = True
     | c >= '\x7f' = True
     | otherwise   = False
 
--- |@'isSeparator' c@ is True iff c is one of HTTP separators.
+-- |@'isSeparator' c@ is 'Prelude.True' iff c is one of HTTP
+-- separators.
 isSeparator :: Char -> Bool
 isSeparator '('  = True
 isSeparator ')'  = True
@@ -50,7 +51,7 @@ isSeparator ' '  = True
 isSeparator '\t' = True
 isSeparator _    = False
 
--- |@'isChar' c@ is True iff @c <= 0x7f@.
+-- |@'isChar' c@ is 'Prelude.True' iff @c <= 0x7f@.
 isChar :: Char -> Bool
 isChar c
     | c <= '\x7f' = True
index 2cd06cc9cac7f79f2870e3da1847c57f8e089350..e9300a5d3def1fe31fe564f336f231fbe25499ca 100644 (file)
@@ -19,7 +19,8 @@ month =  ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
 week :: [String]
 week =  ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
 
--- |Format a @CalendarTime@ to RFC 1123 Date and Time string.
+-- |Format a 'System.Time.CalendarTime' to RFC 1123 Date and Time
+-- string.
 formatRFC1123DateTime :: CalendarTime -> String
 formatRFC1123DateTime time
     = time `seq`
@@ -41,8 +42,8 @@ formatRFC1123DateTime time
       id       (ctTZName time)
       
 
--- |Format a @ClockTime@ to HTTP Date and Time. Time zone will be
--- always UTC but prints as GMT.
+-- |Format a 'System.Time.ClockTime' to HTTP Date and Time. Time zone
+-- will be always UTC but prints as GMT.
 formatHTTPDateTime :: ClockTime -> String
 formatHTTPDateTime time
     = time `seq`
index 8942c762da36fa8104efe762288d1de33f0a6721..8e25904ac927d00da9d96fecdfff998328f7d6d7 100644 (file)
@@ -1,8 +1,9 @@
 -- #prune
 
 -- |This is the Resource Monad; monadic actions to define the behavior
--- of each resources. The 'Resource' Monad is a kind of IO Monad thus
--- it implements MonadIO class. It is also a state machine.
+-- of each resources. The 'Resource' Monad is a kind of 'Prelude.IO'
+-- Monad thus it implements 'Control.Monad.Trans.MonadIO' class. It is
+-- also a state machine.
 -- 
 -- Request Processing Flow:
 --
@@ -61,6 +62,7 @@ module Network.HTTP.Lucu.Resource
     (
     -- * Monad
     Resource
+    , runRes -- private
 
     -- * Actions
 
@@ -100,8 +102,8 @@ module Network.HTTP.Lucu.Resource
     -- Body/.
     , input
     , inputChunk
-    , inputBS
-    , inputChunkBS
+    , inputLBS
+    , inputChunkLBS
     , inputForm
     , defaultLimit
 
@@ -122,8 +124,8 @@ module Network.HTTP.Lucu.Resource
     -- Body/.
     , output
     , outputChunk
-    , outputBS
-    , outputChunkBS
+    , outputLBS
+    , outputChunkLBS
 
     , driftTo
     )
@@ -132,8 +134,8 @@ module Network.HTTP.Lucu.Resource
 import           Control.Concurrent.STM
 import           Control.Monad.Reader
 import           Data.Bits
+import           Data.ByteString.Base (LazyByteString)
 import qualified Data.ByteString.Lazy.Char8 as B
-import           Data.ByteString.Lazy.Char8 (ByteString)
 import           Data.List
 import           Data.Maybe
 import           Network.HTTP.Lucu.Abortion
@@ -155,27 +157,50 @@ import           Network.Socket
 import           Network.URI
 import           System.Time
 
--- |The 'Resource' monad. /Interaction/ is an internal state thus it
--- is not exposed to users. This monad implements 'MonadIO' so it can
--- do any IO actions.
-type Resource a = ReaderT Interaction IO a
+-- |The 'Resource' monad. This monad implements
+-- 'Control.Monad.Trans.MonadIO' so it can do any 'Prelude.IO'
+-- actions.
+newtype Resource a = Resource { unRes :: ReaderT Interaction IO a }
+
+instance Functor Resource where
+    fmap f c = Resource (fmap f (unRes c))
+
+instance Monad Resource where
+    c >>= f = Resource (unRes c >>= unRes . f)
+    return  = Resource . return
+    fail    = Resource . fail
+
+instance MonadIO Resource where
+    liftIO = Resource . liftIO
+
+
+runRes :: Resource a -> Interaction -> IO a
+runRes r itr
+    = runReaderT (unRes r) itr
+
+
+getInteraction :: Resource Interaction
+getInteraction = Resource ask
+
 
 -- |Get the 'Network.HTTP.Lucu.Config.Config' value which is used for
 -- the httpd.
 getConfig :: Resource Config
-getConfig = do itr <- ask
+getConfig = do itr <- getInteraction
                return $! itrConfig itr
 
 
--- |Get the SockAddr of the remote host. If you want a string
--- representation instead of SockAddr, use 'getRemoteAddr''.
+-- |Get the 'Network.Socket.SockAddr' of the remote host. If you want
+-- a string representation instead of 'Network.Socket.SockAddr', use
+-- 'getRemoteAddr''.
 getRemoteAddr :: Resource SockAddr
-getRemoteAddr = do itr <- ask
+getRemoteAddr = do itr <- getInteraction
                    return $! itrRemoteAddr itr
 
 
 -- |Get the string representation of the address of remote host. If
--- you want a SockAddr instead of String, use 'getRemoteAddr'.
+-- you want a 'Network.Socket.SockAddr' instead of String, use
+-- 'getRemoteAddr'.
 getRemoteAddr' :: Resource String
 getRemoteAddr' = do addr <- getRemoteAddr
                     case addr of
@@ -194,7 +219,7 @@ getRemoteAddr' = do addr <- getRemoteAddr
 -- |Get the 'Network.HTTP.Lucu.Request.Request' value which represents
 -- the request header. In general you don't have to use this action.
 getRequest :: Resource Request
-getRequest = do itr <- ask
+getRequest = do itr <- getInteraction
                 req <- liftIO $! atomically $! readItr itr itrRequest fromJust
                 return req
 
@@ -236,7 +261,7 @@ getRequestVersion = do req <- getRequest
 -- >   , ...
 -- >   }
 getResourcePath :: Resource [String]
-getResourcePath = do itr <- ask
+getResourcePath = do itr <- getInteraction
                      return $! fromJust $! itrResourcePath itr
 
 
@@ -368,7 +393,7 @@ foundEntity tag timeStamp
 -- 'foundETag' doesn't (and can't) put \"Last-Modified\" header into
 -- the response.
 --
--- This action is not preferred. You should use 'foundEntity' when
+-- This action is not preferred. You should use 'foundEntity' whenever
 -- possible.
 foundETag :: ETag -> Resource ()
 foundETag tag
@@ -424,7 +449,7 @@ foundETag tag
 -- modification time are unsafe because it is possible to mess up such
 -- tests by modifying the entity twice in a second.
 --
--- This action is not preferred. You should use 'foundEntity' when
+-- This action is not preferred. You should use 'foundEntity' whenever
 -- possible.
 foundTimeStamp :: ClockTime -> Resource ()
 foundTimeStamp timeStamp
@@ -509,23 +534,25 @@ foundNoEntity msgM
 -- ('Network.HTTP.Lucu.Config.cnfMaxEntityLength') is used. See
 -- 'defaultLimit'.
 --
--- Note that 'inputBS' is more efficient than 'input' so you should
+-- Note that 'inputLBS' is more efficient than 'input' so you should
 -- use it whenever possible.
 input :: Int -> Resource String
 input limit = limit `seq`
-              inputBS limit >>= return . B.unpack
+              inputLBS limit >>= return . B.unpack
 
 
 -- | This is mostly the same as 'input' but is more
--- efficient. 'inputBS' returns a lazy ByteString but it's not really
--- lazy: reading from the socket just happens at the computation of
--- 'inputBS', not at the lazy evaluation of the ByteString. The same
--- goes for 'inputChunkBS'.
-inputBS :: Int -> Resource ByteString
-inputBS limit
+-- efficient. 'inputLBS' returns a
+-- 'Data.ByteString.Base.LazyByteString' but it's not really lazy:
+-- reading from the socket just happens at the computation of
+-- 'inputLBS', not at the evaluation of the
+-- 'Data.ByteString.Base.LazyByteString'. The same goes for
+-- 'inputChunkLBS'.
+inputLBS :: Int -> Resource LazyByteString
+inputLBS limit
     = limit `seq`
       do driftTo GettingBody
-         itr     <- ask
+         itr     <- getInteraction
          hasBody <- liftIO $! atomically $! readItr itr itrRequestHasBody id
          chunk   <- if hasBody then
                         askForInput itr
@@ -534,7 +561,7 @@ inputBS limit
                            return B.empty
          return chunk
     where
-      askForInput :: Interaction -> Resource ByteString
+      askForInput :: Interaction -> Resource LazyByteString
       askForInput itr
           = itr `seq`
             do let defaultLimit = cnfMaxEntityLength $ itrConfig itr
@@ -543,7 +570,7 @@ inputBS limit
                                   else
                                       limit
                when (actualLimit <= 0)
-                        $ fail ("inputBS: limit must be positive: " ++ show actualLimit)
+                        $ fail ("inputLBS: limit must be positive: " ++ show actualLimit)
                -- Reader にリクエスト
                liftIO $! atomically
                           $! do chunkLen <- readItr itr itrReqChunkLength id
@@ -592,20 +619,20 @@ inputBS limit
 -- ('Network.HTTP.Lucu.Config.cnfMaxEntityLength') is used. See
 -- 'defaultLimit'.
 --
--- Note that 'inputChunkBS' is more efficient than 'inputChunk' so you
+-- Note that 'inputChunkLBS' is more efficient than 'inputChunk' so you
 -- should use it whenever possible.
 inputChunk :: Int -> Resource String
 inputChunk limit = limit `seq`
-                   inputChunkBS limit >>= return . B.unpack
+                   inputChunkLBS limit >>= return . B.unpack
 
 
 -- | This is mostly the same as 'inputChunk' but is more
--- efficient. See 'inputBS'.
-inputChunkBS :: Int -> Resource ByteString
-inputChunkBS limit
+-- efficient. See 'inputLBS'.
+inputChunkLBS :: Int -> Resource LazyByteString
+inputChunkLBS limit
     = limit `seq`
       do driftTo GettingBody
-         itr <- ask
+         itr     <- getInteraction
          hasBody <- liftIO $ atomically $ readItr itr itrRequestHasBody id
          chunk   <- if hasBody then
                         askForInput itr
@@ -614,7 +641,7 @@ inputChunkBS limit
                            return B.empty
          return chunk
     where
-      askForInput :: Interaction -> Resource ByteString
+      askForInput :: Interaction -> Resource LazyByteString
       askForInput itr
           = itr `seq`
             do let defaultLimit = cnfMaxEntityLength $! itrConfig itr
@@ -623,7 +650,7 @@ inputChunkBS limit
                                   else
                                       limit
                when (actualLimit <= 0)
-                        $ fail ("inputChunkBS: limit must be positive: " ++ show actualLimit)
+                        $ fail ("inputChunkLBS: limit must be positive: " ++ show actualLimit)
                -- Reader にリクエスト
                liftIO $! atomically
                           $! do writeItr itr itrReqBodyWanted $! Just actualLimit
@@ -677,7 +704,7 @@ inputForm limit
           = abort UnsupportedMediaType []
             (Just $! "Sorry, inputForm does not currently support multipart/form-data.")
 
--- | This is just a constant -1. It's better to say @'input'
+-- | This is just a constant @-1@. It's better to say @'input'
 -- 'defaultLimit'@ than to say @'input' (-1)@ but these are exactly
 -- the same.
 defaultLimit :: Int
@@ -693,7 +720,7 @@ setStatus :: StatusCode -> Resource ()
 setStatus code
     = code `seq`
       do driftTo DecidingHeader
-         itr <- ask
+         itr <- getInteraction
          liftIO $! atomically $! updateItr itr itrResponse
                     $! \ res -> res {
                                   resStatus = code
@@ -722,13 +749,13 @@ setHeader name value
 setHeader' :: String -> String -> Resource ()
 setHeader' name value
     = name `seq` value `seq`
-      do itr <- ask
+      do itr <- getInteraction
          liftIO $ atomically
                     $ updateItr itr itrResponse
                           $ H.setHeader name value
 
 -- | Computation of @'redirect' code uri@ sets the response status to
--- @code@ and \"Location\" header to @uri@. @code@ must satisfy
+-- @code@ and \"Location\" header to @uri@. The @code@ must satisfy
 -- 'Network.HTTP.Lucu.Response.isRedirection' or it causes an error.
 redirect :: StatusCode -> URI -> Resource ()
 redirect code uri
@@ -771,35 +798,35 @@ setContentEncoding codings
 -- apply 'output' to an infinite string, such as a lazy stream of
 -- \/dev\/random.
 --
--- Note that 'outputBS' is more efficient than 'output' so you should
+-- Note that 'outputLBS' is more efficient than 'output' so you should
 -- use it whenever possible.
 output :: String -> Resource ()
-output str = outputBS $! B.pack str
+output str = outputLBS $! B.pack str
 {-# INLINE output #-}
 
 -- | This is mostly the same as 'output' but is more efficient.
-outputBS :: ByteString -> Resource ()
-outputBS str = do outputChunkBS str
-                  driftTo Done
-{-# INLINE outputBS #-}
+outputLBS :: LazyByteString -> Resource ()
+outputLBS str = do outputChunkLBS str
+                   driftTo Done
+{-# INLINE outputLBS #-}
 
 -- | Computation of @'outputChunk' str@ writes @str@ as a part of
 -- response body. You can compute this action multiple times to write
 -- a body little at a time. It is safe to apply 'outputChunk' to an
 -- infinite string.
 --
--- Note that 'outputChunkBS' is more efficient than 'outputChunk' so
+-- Note that 'outputChunkLBS' is more efficient than 'outputChunk' so
 -- you should use it whenever possible.
 outputChunk :: String -> Resource ()
-outputChunk str = outputChunkBS $! B.pack str
+outputChunk str = outputChunkLBS $! B.pack str
 {-# INLINE outputChunk #-}
 
 -- | This is mostly the same as 'outputChunk' but is more efficient.
-outputChunkBS :: ByteString -> Resource ()
-outputChunkBS str
+outputChunkLBS :: LazyByteString -> Resource ()
+outputChunkLBS str
     = str `seq`
       do driftTo DecidingBody
-         itr <- ask
+         itr <- getInteraction
          
          let limit = cnfMaxOutputChunkLength $ itrConfig itr
          when (limit <= 0)
@@ -816,17 +843,16 @@ outputChunkBS str
                     $ liftIO $ atomically $
                       writeItr itr itrBodyIsNull False
     where
-      {- チャンクの大きさは Config で制限されてゐる。もし例へば
-         /dev/zero を B.readFile して作った ByteString をそのまま
-         ResponseWriter に渡したりすると大變な事が起こる。何故なら
-         ResponseWriter はTransfer-Encoding: chunked の時、ヘッダを書く
-         爲にチャンクの大きさを測るから、その時に起こるであらう事は言ふ
-         までも無い。 -}
-      sendChunks :: ByteString -> Int -> Resource ()
+      -- チャンクの大きさは Config で制限されてゐる。もし例へば
+      -- "/dev/zero" を B.readFile して作った LazyByteString をそのまま
+      -- ResponseWriter に渡したりすると大變な事が起こる。何故なら
+      -- ResponseWriter は Transfer-Encoding: chunked の時、ヘッダを書
+      -- く爲にチャンクの大きさを測る。
+      sendChunks :: LazyByteString -> Int -> Resource ()
       sendChunks str limit
           | B.null str = return ()
           | otherwise  = do let (chunk, remaining) = B.splitAt (fromIntegral limit) str
-                            itr <- ask
+                            itr <- getInteraction
                             liftIO $ atomically $ 
                                    do buf <- readItr itr itrBodyToSend id
                                       if B.null buf then
@@ -860,7 +886,7 @@ outputChunkBS str
 driftTo :: InteractionState -> Resource ()
 driftTo newState
     = newState `seq`
-      do itr <- ask
+      do itr <- getInteraction
          liftIO $ atomically $ do oldState <- readItr itr itrState id
                                   if newState < oldState then
                                       throwStateError oldState newState
diff --git a/Network/HTTP/Lucu/Resource.hs-boot b/Network/HTTP/Lucu/Resource.hs-boot
deleted file mode 100644 (file)
index 77fdfb9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-{- -*- haskell -*- -}
-module Network.HTTP.Lucu.Resource
-    where
-
-import           Control.Monad.Reader
-import           Network.HTTP.Lucu.Interaction
-
-type Resource a = ReaderT Interaction IO a
\ No newline at end of file
index c2f6add5483b2e19a653ce1d25f51510407a65ad..149fa9d92d3b5101a27f5ba6c334133a3921fe34 100644 (file)
@@ -14,7 +14,7 @@ module Network.HTTP.Lucu.Resource.Tree
 import           Control.Concurrent
 import           Control.Concurrent.STM
 import           Control.Exception
-import           Control.Monad.Reader
+import           Control.Monad
 import           Data.Dynamic
 import           Data.List
 import qualified Data.Map as M
@@ -41,9 +41,11 @@ import           Prelude hiding (catch)
 -- | 'ResourceDef' is basically a set of
 -- 'Network.HTTP.Lucu.Resource.Resource' monads for each HTTP methods.
 data ResourceDef = ResourceDef {
-    -- | Whether to run a 'Network.HTTP.Lucu.Resource.Resource' on a
-    -- native thread (spawned using @forkOS@) or to run it on a user
-    -- thread (spanwed using @forkIO@). Generally you don't
+    -- |Whether to run a 'Network.HTTP.Lucu.Resource.Resource' on a
+    -- native thread (spawned by 'Control.Concurrent.forkOS') or to
+    -- run it on a user thread (spanwed by
+    -- 'Control.Concurrent.forkIO'). Generally you don't need to set
+    -- this field to 'Prelude.True'.
       resUsesNativeThread :: !Bool
     -- | Whether to be greedy or not.
     -- 
@@ -168,10 +170,10 @@ runResource :: ResourceDef -> Interaction -> IO ThreadId
 runResource def itr
     = def `seq` itr `seq`
       fork
-      $! catch ( runReaderT ( do req <- getRequest
-                                 fromMaybe notAllowed $ rsrc req
-                                 driftTo Done
-                            ) itr
+      $! catch ( runRes ( do req <- getRequest
+                             fromMaybe notAllowed $ rsrc req
+                             driftTo Done
+                        ) itr
                )
              $ \ exc -> processException exc
     where
@@ -227,7 +229,7 @@ runResource def itr
                reqM  <- atomically $ readItr itr itrRequest id
                res   <- atomically $ readItr itr itrResponse id
                if state <= DecidingHeader then
-                   flip runReaderT itr
+                   flip runRes itr
                       $ do setStatus $ aboStatus abo
                            -- FIXME: 同じ名前で複數の値があった時は、こ
                            -- れではまずいと思ふ。
@@ -237,7 +239,7 @@ runResource def itr
                    when (cnfDumpTooLateAbortionToStderr $ itrConfig itr)
                             $ hPutStrLn stderr $ show abo
 
-               flip runReaderT itr $ driftTo Done
+               flip runRes itr $ driftTo Done
 
       formatIOE :: IOError -> String
       formatIOE ioE = if isUserError ioE then
index 913c491f6f1242373f4c52d9ef10a62a9ddd781e..9239cba0462ec3e889771da1acff3162f4409103 100644 (file)
@@ -78,7 +78,7 @@ data StatusCode = Continue
                   deriving (Typeable, Eq)
 
 instance Show StatusCode where
-    show sc = let (num, msg) = statusCode sc
+    show sc = let (# num, msg #) = statusCode sc
               in
                 (fmtDec 3 num) ++ " " ++ msg
 
@@ -109,87 +109,87 @@ hPutStatus h sc
     = h `seq` sc `seq`
       hPutStr h (show sc)
 
--- |@'isInformational' sc@ is True iff @sc < 200@.
+-- |@'isInformational' sc@ is 'Prelude.True' iff @sc < 200@.
 isInformational :: StatusCode -> Bool
 isInformational = doesMeet (< 200)
 
--- |@'isSuccessful' sc@ is True iff @200 <= sc < 300@.
+-- |@'isSuccessful' sc@ is 'Prelude.True' iff @200 <= sc < 300@.
 isSuccessful :: StatusCode -> Bool
 isSuccessful = doesMeet (\ n -> n >= 200 && n < 300)
 
--- |@'isRedirection' sc@ is True iff @300 <= sc < 400@.
+-- |@'isRedirection' sc@ is 'Prelude.True' iff @300 <= sc < 400@.
 isRedirection :: StatusCode -> Bool
 isRedirection = doesMeet (\ n -> n >= 300 && n < 400)
 
--- |@'isError' sc@ is True iff @400 <= sc@
+-- |@'isError' sc@ is 'Prelude.True' iff @400 <= sc@
 isError :: StatusCode -> Bool
 isError = doesMeet (>= 400)
 
--- |@'isClientError' sc@ is True iff @400 <= sc < 500@.
+-- |@'isClientError' sc@ is 'Prelude.True' iff @400 <= sc < 500@.
 isClientError :: StatusCode -> Bool
 isClientError = doesMeet (\ n -> n >= 400 && n < 500)
 
--- |@'isServerError' sc@ is True iff @500 <= sc@.
+-- |@'isServerError' sc@ is 'Prelude.True' iff @500 <= sc@.
 isServerError :: StatusCode -> Bool
 isServerError = doesMeet (>= 500)
 
 
 doesMeet :: (Int -> Bool) -> StatusCode -> Bool
-doesMeet p sc = let (num, _) = statusCode sc
+doesMeet p sc = let (# num, _ #) = statusCode sc
                 in
                   p num
 
 
 -- |@'statusCode' sc@ returns a tuple of numeric and textual
 -- representation of @sc@.
-statusCode :: StatusCode -> (Int, String)
-statusCode Continue                    = (100, "Continue")
-statusCode SwitchingProtocols          = (101, "Switching Protocols")
-statusCode Processing                  = (102, "Processing")
+statusCode :: StatusCode -> (# Int, String #)
+statusCode Continue                    = (# 100, "Continue" #)
+statusCode SwitchingProtocols          = (# 101, "Switching Protocols" #)
+statusCode Processing                  = (# 102, "Processing" #)
 --
-statusCode Ok                          = (200, "OK")
-statusCode Created                     = (201, "Created")
-statusCode Accepted                    = (202, "Accepted")
-statusCode NonAuthoritativeInformation = (203, "Non Authoritative Information")
-statusCode NoContent                   = (204, "No Content")
-statusCode ResetContent                = (205, "Reset Content")
-statusCode PartialContent              = (206, "Partial Content")
-statusCode MultiStatus                 = (207, "Multi Status")
+statusCode Ok                          = (# 200, "OK" #)
+statusCode Created                     = (# 201, "Created" #)
+statusCode Accepted                    = (# 202, "Accepted" #)
+statusCode NonAuthoritativeInformation = (# 203, "Non Authoritative Information" #)
+statusCode NoContent                   = (# 204, "No Content" #)
+statusCode ResetContent                = (# 205, "Reset Content" #)
+statusCode PartialContent              = (# 206, "Partial Content" #)
+statusCode MultiStatus                 = (# 207, "Multi Status" #)
 --
-statusCode MultipleChoices             = (300, "Multiple Choices")
-statusCode MovedPermanently            = (301, "Moved Permanently")
-statusCode Found                       = (302, "Found")
-statusCode SeeOther                    = (303, "See Other")
-statusCode NotModified                 = (304, "Not Modified")
-statusCode UseProxy                    = (305, "Use Proxy")
-statusCode TemporaryRedirect           = (306, "Temporary Redirect")
+statusCode MultipleChoices             = (# 300, "Multiple Choices" #)
+statusCode MovedPermanently            = (# 301, "Moved Permanently" #)
+statusCode Found                       = (# 302, "Found" #)
+statusCode SeeOther                    = (# 303, "See Other" #)
+statusCode NotModified                 = (# 304, "Not Modified" #)
+statusCode UseProxy                    = (# 305, "Use Proxy" #)
+statusCode TemporaryRedirect           = (# 306, "Temporary Redirect" #)
 --
-statusCode BadRequest                  = (400, "Bad Request")
-statusCode Unauthorized                = (401, "Unauthorized")
-statusCode PaymentRequired             = (402, "Payment Required")
-statusCode Forbidden                   = (403, "Forbidden")
-statusCode NotFound                    = (404, "Not Found")
-statusCode MethodNotAllowed            = (405, "Method Not Allowed")
-statusCode NotAcceptable               = (406, "Not Acceptable")
-statusCode ProxyAuthenticationRequired = (407, "Proxy Authentication Required")
-statusCode RequestTimeout              = (408, "Request Timeout")
-statusCode Conflict                    = (409, "Conflict")
-statusCode Gone                        = (410, "Gone")
-statusCode LengthRequired              = (411, "Length Required")
-statusCode PreconditionFailed          = (412, "Precondition Failed")
-statusCode RequestEntityTooLarge       = (413, "Request Entity Too Large")
-statusCode RequestURITooLarge          = (414, "Request URI Too Large")
-statusCode UnsupportedMediaType        = (415, "Unsupported Media Type")
-statusCode RequestRangeNotSatisfiable  = (416, "Request Range Not Satisfiable")
-statusCode ExpectationFailed           = (417, "Expectation Failed")
-statusCode UnprocessableEntitiy        = (422, "Unprocessable Entity")
-statusCode Locked                      = (423, "Locked")
-statusCode FailedDependency            = (424, "Failed Dependency")
+statusCode BadRequest                  = (# 400, "Bad Request" #)
+statusCode Unauthorized                = (# 401, "Unauthorized" #)
+statusCode PaymentRequired             = (# 402, "Payment Required" #)
+statusCode Forbidden                   = (# 403, "Forbidden" #)
+statusCode NotFound                    = (# 404, "Not Found" #)
+statusCode MethodNotAllowed            = (# 405, "Method Not Allowed" #)
+statusCode NotAcceptable               = (# 406, "Not Acceptable" #)
+statusCode ProxyAuthenticationRequired = (# 407, "Proxy Authentication Required" #)
+statusCode RequestTimeout              = (# 408, "Request Timeout" #)
+statusCode Conflict                    = (# 409, "Conflict" #)
+statusCode Gone                        = (# 410, "Gone" #)
+statusCode LengthRequired              = (# 411, "Length Required" #)
+statusCode PreconditionFailed          = (# 412, "Precondition Failed" #)
+statusCode RequestEntityTooLarge       = (# 413, "Request Entity Too Large" #)
+statusCode RequestURITooLarge          = (# 414, "Request URI Too Large" #)
+statusCode UnsupportedMediaType        = (# 415, "Unsupported Media Type" #)
+statusCode RequestRangeNotSatisfiable  = (# 416, "Request Range Not Satisfiable" #)
+statusCode ExpectationFailed           = (# 417, "Expectation Failed" #)
+statusCode UnprocessableEntitiy        = (# 422, "Unprocessable Entity" #)
+statusCode Locked                      = (# 423, "Locked" #)
+statusCode FailedDependency            = (# 424, "Failed Dependency" #)
 --
-statusCode InternalServerError         = (500, "Internal Server Error")
-statusCode NotImplemented              = (501, "Not Implemented")
-statusCode BadGateway                  = (502, "Bad Gateway")
-statusCode ServiceUnavailable          = (503, "Service Unavailable")
-statusCode GatewayTimeout              = (504, "Gateway Timeout")
-statusCode HttpVersionNotSupported     = (505, "HTTP Version Not Supported")
-statusCode InsufficientStorage         = (507, "Insufficient Storage")
\ No newline at end of file
+statusCode InternalServerError         = (# 500, "Internal Server Error" #)
+statusCode NotImplemented              = (# 501, "Not Implemented" #)
+statusCode BadGateway                  = (# 502, "Bad Gateway" #)
+statusCode ServiceUnavailable          = (# 503, "Service Unavailable" #)
+statusCode GatewayTimeout              = (# 504, "Gateway Timeout" #)
+statusCode HttpVersionNotSupported     = (# 505, "HTTP Version Not Supported" #)
+statusCode InsufficientStorage         = (# 507, "Insufficient Storage" #)
\ No newline at end of file
index 3b8222f15f0d07f06cf4aaaf884cf5e754515d5f..12cf78b0729c760c82e6f35faa08909f6d53b876 100644 (file)
@@ -73,7 +73,7 @@ handleStaticFile path
                   Just mime -> setContentType mime
 
                 -- 實際にファイルを讀んで送る
-                (liftIO $ B.readFile path) >>= outputBS
+                (liftIO $ B.readFile path) >>= outputLBS
            else
              do isDir <- liftIO $ doesDirectoryExist path
                 if isDir then
index d92516ee15875a6791fc912b8d11ebe1eb765ffb..0c29836592e72be3354bf6e6fc2826f5cd666ace 100644 (file)
@@ -40,7 +40,8 @@ trim p = p `seq` trimTail . trimHead
       trimHead = dropWhile p
       trimTail = reverse . trimHead . reverse
 
--- |@'noCaseEq' a b@ is equivalent to @(map toLower a) == (map toLower
+-- |@'noCaseEq' a b@ is equivalent to @('Prelude.map'
+-- 'Data.Char.toLower' a) == ('Prelude.map' 'Data.Char.toLower'
 -- b)@. See 'noCaseEq''.
 noCaseEq :: String -> String -> Bool
 noCaseEq a b
@@ -55,7 +56,8 @@ noCaseEq' a b
     | otherwise            = noCaseEq a b
 {-# INLINE noCaseEq' #-}
 
--- |@'isWhiteSpace' c@ is True iff c is one of SP, HT, CR and LF.
+-- |@'isWhiteSpace' c@ is 'Prelude.True' iff c is one of SP, HT, CR
+-- and LF.
 isWhiteSpace :: Char -> Bool
 isWhiteSpace ' '  = True
 isWhiteSpace '\t' = True