]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Resource.hs
Still making many changes...
[Lucu.git] / Network / HTTP / Lucu / Resource.hs
index d0454c4c630d047a419f335a37ecfeb1c64211cb..ddff647364a4295361379926b5affcff571a7081 100644 (file)
@@ -131,12 +131,13 @@ module Network.HTTP.Lucu.Resource
 
     -- |Computation of these actions changes the state to /Deciding
     -- Body/.
-    , output
-    , outputChunk
+    , putChunk
+    , putBuilder
 
     , driftTo -- private
     )
     where
+import Blaze.ByteString.Builder (Builder)
 import qualified Blaze.ByteString.Builder.ByteString as BB
 import Control.Applicative
 import Control.Concurrent.STM
@@ -410,7 +411,7 @@ getAuthorization
              return ac
 
 
-{- ExaminingRequest 時に使用するアクション群 -}
+-- Finding an entity
 
 -- |Tell the system that the 'Resource' found an entity for the
 -- request URI. If this is a GET or HEAD request, a found entity means
@@ -583,7 +584,7 @@ foundNoEntity msgM
          driftTo GettingBody
 
 
-{- GettingBody 時に使用するアクション群 -}
+-- Getting a request body
 
 -- | Computation of @'input' limit@ attempts to read the request body
 -- up to @limit@ bytes, and then make the 'Resource' transit to
@@ -775,7 +776,7 @@ defaultLimit ∷ Int
 defaultLimit = (-1)
 
 
-{- DecidingHeader 時に使用するアクション群 -}
+-- Setting response headers
 
 -- | Set the response status code. If you omit to compute this action,
 -- the status code will be defaulted to \"200 OK\".
@@ -869,48 +870,54 @@ setWWWAuthenticate challenge
     = setHeader "WWW-Authenticate" (printAuthChallenge challenge)
 
 
-{- DecidingBody 時に使用するアクション群 -}
+-- Writing a response body
 
--- | Write a 'Lazy.ByteString' to the response body, and then transit
--- to the /Done/ state. It is safe to apply 'output' to an infinite
--- string, such as the lazy stream of \/dev\/random.
+-- | Write a chunk in 'Lazy.ByteString' to the response body. It is
+-- safe to apply this function to an infinitely long
+-- 'Lazy.ByteString'.
 --
--- Note that you must first set the \"Content-Type\" response header
+-- Note that you must first set the response header \"Content-Type\"
 -- before applying this function. See: 'setContentType'
-output ∷ Lazy.ByteString → Resource ()
-{-# INLINE output #-}
-output str = outputChunk str *> driftTo Done
+putChunk ∷ Lazy.ByteString → Resource ()
+{-# INLINE putChunk #-}
+putChunk = putBuilder ∘ BB.fromLazyByteString
 
--- | Write a 'Lazy.ByteString' to the response body. This action can
--- be repeated as many times as you want. It is safe to apply
--- 'outputChunk' to an infinite string.
+-- | Run a 'Builder' to construct a chunk, and write it to the
+-- response body. It is safe to apply this function to a 'Builder'
+-- producing an infinitely long stream of octets.
 --
--- Note that you must first set the \"Content-Type\" response header
+-- Note that you must first set the response header \"Content-Type\"
 -- before applying this function. See: 'setContentType'
-outputChunk ∷ Lazy.ByteString → Resource ()
-outputChunk str
-    = do driftTo DecidingBody
-         itr ← getInteraction
+putBuilder ∷ Builder → Resource ()
+putBuilder b
+    = do itr ← getInteraction
          liftIO $ atomically
-                $ do hasCType ← readTVar $ itrResponseHasCType itr
+                $ do driftTo' itr DecidingBody
+                     hasCType ← readTVar $ itrResponseHasCType itr
                      unless hasCType
                          $ abortSTM InternalServerError []
-                         $ Just "outputChunk: Content-Type has not been set."
-                     putTMVar (itrBodyToSend itr) (BB.fromLazyByteString str)
+                         $ Just "putBuilder: Content-Type has not been set."
+                     putTMVar (itrBodyToSend itr) b
+
+
+-- Private
 
 driftTo ∷ InteractionState → Resource ()
 driftTo newState
     = do itr ← getInteraction
-         liftIO $ atomically
-                $ do oldState ← readTVar $ itrState itr
-                     if newState < oldState then
-                         throwStateError oldState newState
-                     else
-                         do let a = [oldState .. newState]
-                                b = tail a
-                                c = zip a b
-                            mapM_ (uncurry $ drift itr) c
-                            writeTVar (itrState itr) newState
+         liftIO $ atomically $ driftTo' itr newState
+
+driftTo' ∷ Interaction → InteractionState → STM ()
+driftTo' itr@(Interaction {..}) newState
+    = do oldState ← readTVar itrState
+         if newState < oldState then
+             throwStateError oldState newState
+         else
+             do let a = [oldState .. newState]
+                    b = tail a
+                    c = zip a b
+                mapM_ (uncurry drift) c
+                writeTVar itrState newState
     where
       throwStateError ∷ Monad m ⇒ InteractionState → InteractionState → m a
       throwStateError Done DecidingBody
@@ -918,10 +925,10 @@ driftTo newState
       throwStateError old new
           = fail ("state error: " ⧺ show old ⧺ " ==> " ⧺ show new)
 
-      drift ∷ Interaction → InteractionState → InteractionState → STM ()
-      drift (Interaction {..}) GettingBody _
+      drift ∷ InteractionState → InteractionState → STM ()
+      drift GettingBody _
           = writeTVar itrReqBodyWasteAll True
-      drift itr DecidingHeader _
+      drift DecidingHeader _
           = postprocess itr
-      drift _ _ _
+      drift _ _
           = return ()