]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Abortion.hs
Many many changes
[Lucu.git] / Network / HTTP / Lucu / Abortion.hs
index 091b1bb9a03f8298b56f674959aafd0efda6d947..6c2d14dd8c9e00cb09923df93b2097975d736ac7 100644 (file)
@@ -1,9 +1,15 @@
--- #prune
+{-# LANGUAGE
+    Arrows
+  , DeriveDataTypeable
+  , TypeOperators
+  , UnicodeSyntax
+  #-}
 
 -- |Aborting the computation of 'Network.HTTP.Lucu.Resource.Resource'
 -- in any 'Prelude.IO' monads or arrows.
 module Network.HTTP.Lucu.Abortion
     ( Abortion(..)
+
     , abort
     , abortPurely
     , abortSTM
@@ -11,40 +17,42 @@ module Network.HTTP.Lucu.Abortion
     , abortPage
     )
     where
-
-import           Control.Arrow
-import           Control.Arrow.ArrowIO
-import           Control.Concurrent.STM
-import           Control.Exception
-import           Control.Monad.Trans
-import           Data.ByteString.Base (ByteString)
-import           Data.Dynamic
-import           GHC.Conc (unsafeIOToSTM)
-import           Network.HTTP.Lucu.Config
-import           Network.HTTP.Lucu.DefaultPage
-import           Network.HTTP.Lucu.Headers
-import           Network.HTTP.Lucu.Request
-import           Network.HTTP.Lucu.Response
-import           System.IO.Unsafe
-import           Text.XML.HXT.Arrow.WriteDocument
-import           Text.XML.HXT.Arrow.XmlArrow
-import           Text.XML.HXT.Arrow.XmlIOStateArrow
-import           Text.XML.HXT.DOM.XmlKeywords
-
+import Blaze.ByteString.Builder (Builder)
+import qualified Blaze.ByteString.Builder.Char.Utf8 as BB
+import Control.Arrow.ArrowIO
+import Control.Arrow.ListArrow
+import Control.Arrow.Unicode
+import Control.Concurrent.STM
+import Control.Exception
+import Control.Monad.Trans
+import Data.Ascii (Ascii, CIAscii)
+import Data.Text (Text)
+import qualified Data.Text as T
+import Data.Typeable
+import Network.HTTP.Lucu.Config
+import Network.HTTP.Lucu.DefaultPage
+import Network.HTTP.Lucu.Headers
+import Network.HTTP.Lucu.Request
+import Network.HTTP.Lucu.Response
+import Prelude.Unicode
+import Text.XML.HXT.Arrow.WriteDocument
+import Text.XML.HXT.Arrow.XmlArrow
+import Text.XML.HXT.Arrow.XmlState
 
 data Abortion = Abortion {
-      aboStatus  :: !StatusCode
-    , aboHeaders :: !Headers
-    , aboMessage :: !(Maybe String)
-    } deriving (Show, Typeable)
+      aboStatus  ∷ !StatusCode
+    , aboHeaders ∷ !Headers
+    , aboMessage ∷ !(Maybe Text)
+    } deriving (Eq, Show, Typeable)
+
+instance Exception Abortion
 
 -- |Computation of @'abort' status headers msg@ aborts the
 -- 'Network.HTTP.Lucu.Resource.Resource' monad with given status,
 -- additional response headers, and optional message string.
 --
--- What this really does is to just throw a special
--- 'Control.Exception.DynException'. The exception will be caught by
--- the Lucu.
+-- What this really does is to throw an instance of 'Exception'. The
+-- exception will be caught by the Lucu system.
 --
 -- 1. If the 'Network.HTTP.Lucu.Resource.Resource' is in the /Deciding
 --    Header/ or any precedent states, it is possible to use the
@@ -53,60 +61,57 @@ data Abortion = Abortion {
 --
 -- 2. Otherwise the HTTP response can't be modified anymore so the
 --    only possible thing the system can do is to dump it to the
---    stderr. See
---    'Network.HTTP.Lucu.Config.cnfDumpTooLateAbortionToStderr'.
+--    stderr. See 'cnfDumpTooLateAbortionToStderr'.
 --
--- Note that the status code doesn't have to be an error code so you
--- can use this action for redirection as well as error reporting e.g.
+-- Note that the status code doesn't necessarily have to be an error
+-- code so you can use this action for redirection as well as error
+-- reporting e.g.
 --
 -- > abort MovedPermanently
 -- >       [("Location", "http://example.net/")]
 -- >       (Just "It has been moved to example.net")
-abort :: MonadIO m => StatusCode -> [ (ByteString, ByteString) ] -> Maybe String -> m a
-abort status headers msg
-    = status `seq` headers `seq` msg `seq`
-      let abo = Abortion status (toHeaders headers) msg
-          exc = DynException (toDyn abo)
-      in
-        liftIO $ throwIO exc
+abort ∷ MonadIO m ⇒ StatusCode → [ (CIAscii, Ascii) ] → Maybe Text → m a
+{-# INLINE abort #-}
+abort status headers
+    = liftIO ∘ throwIO ∘ Abortion status (toHeaders headers)
 
--- |This is similar to 'abort' but compute it with
+-- |This is similar to 'abort' but computes it with
 -- 'System.IO.Unsafe.unsafePerformIO'.
-abortPurely :: StatusCode -> [ (ByteString, ByteString) ] -> Maybe String -> a
-abortPurely = ((unsafePerformIO .) .) . abort
+abortPurely ∷ StatusCode → [ (CIAscii, Ascii) ] → Maybe Text → a
+{-# INLINE abortPurely #-}
+abortPurely status headers
+    = throw ∘ Abortion status (toHeaders headers)
 
 -- |Computation of @'abortSTM' status headers msg@ just computes
 -- 'abort' in a 'Control.Monad.STM.STM' monad.
-abortSTM :: StatusCode -> [ (ByteString, ByteString) ] -> Maybe String -> STM a
-abortSTM status headers msg
-    = status `seq` headers `seq` msg `seq`
-      unsafeIOToSTM $! abort status headers msg
+abortSTM ∷ StatusCode → [ (CIAscii, Ascii) ] → Maybe Text → STM a
+{-# INLINE abortSTM #-}
+abortSTM status headers
+    = throwSTM ∘ Abortion status (toHeaders headers)
 
 -- | Computation of @'abortA' -< (status, (headers, msg))@ just
 -- computes 'abort' in an 'Control.Arrow.ArrowIO.ArrowIO'.
-abortA :: ArrowIO a => a (StatusCode, ([ (ByteString, ByteString) ], Maybe String)) c
-abortA 
-    = arrIO3 abort
+abortA ∷ ArrowIO (⇝) ⇒ (StatusCode, ([ (CIAscii, Ascii) ], Maybe Text)) ⇝ c
+{-# INLINE abortA #-}
+abortA = proc (status, (headers, msg)) →
+         arrIO throwIO ⤙ Abortion status (toHeaders headers) msg
 
 -- aboMessage が Just なら單に mkDefaultPage に渡すだけで良いので樂だが、
 -- Nothing の場合は getDefaultPage を使ってデフォルトのメッセージを得な
 -- ければならない。
-abortPage :: Config -> Maybe Request -> Response -> Abortion -> String
+abortPage ∷ Config → Maybe Request → Response → Abortion → Builder
 abortPage conf reqM res abo
-    = conf `seq` reqM `seq` res `seq` abo `seq`
-      case aboMessage abo of
+    = case aboMessage abo of
         Just msg
-            -> let [html] = unsafePerformIO 
-                            $ runX ( mkDefaultPage conf (aboStatus abo) (txt msg)
-                                     >>>
-                                     writeDocumentToString [(a_indent, v_1)]
-                                   )
-               in
-                 html
+            → let [html] = runLA ( mkDefaultPage conf (aboStatus abo) (txt $ T.unpack msg)
+                                   ⋙
+                                   writeDocumentToString [ withIndent True ]
+                                 ) ()
+              in
+                BB.fromString html
         Nothing
-            -> let res'  = res { resStatus = aboStatus abo }
-                   res'' = foldl (.) id [setHeader name value
-                                             | (name, value) <- fromHeaders $ aboHeaders abo]
-                           $ res'
+            → let res'  = res { resStatus = aboStatus abo }
+                  res'' = foldl (∘) id [setHeader name value
+                                            | (name, value) ← fromHeaders $ aboHeaders abo] res'
                in
                  getDefaultPage conf reqM res''