--- #prune
+{-# LANGUAGE
+ DeriveDataTypeable
+ , UnicodeSyntax
+ #-}
+{-# OPTIONS_HADDOCK prune #-}
-- |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
, abortA
, abortPage
)
where
-
-import Control.Arrow
-import Control.Arrow.ArrowIO
-import Control.Concurrent.STM
-import Control.Exception
-import Control.Monad.Trans
-import GHC.Conc (unsafeIOToSTM)
-import Data.Dynamic
-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 {-# SOURCE #-} Network.HTTP.Lucu.Resource
-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 Control.Arrow
+import Control.Arrow.ArrowIO
+import Control.Concurrent.STM
+import Control.Exception
+import Control.Monad.Trans
+import qualified Data.ByteString.Char8 as C8
+import qualified Data.Text as T
+import Data.Text.Encoding
+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 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)
+ } deriving (Eq, Show, Typeable, Exception)
+
+--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 a special
+-- 'Control.Exception.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
-- > abort MovedPermanently
-- > [("Location", "http://example.net/")]
-- > (Just "It has been moved to example.net")
-abort :: MonadIO m => StatusCode -> [ (String, String) ] -> Maybe String -> m a
+abort :: MonadIO m ⇒ StatusCode → [ (String, String) ] → Maybe String → m a
abort status headers msg
= status `seq` headers `seq` msg `seq`
- let abo = Abortion status headers msg
- exc = DynException (toDyn abo)
+ let abo = Abortion status (toHeaders $ map pack headers) msg
in
- liftIO $ throwIO exc
-{-# SPECIALIZE abort :: StatusCode -> [ (String, String) ] -> Maybe String -> Resource a #-}
+ liftIO $ throwIO abo
+ where
+ pack (x, y) = (C8.pack x, C8.pack y)
+
+-- |This is similar to 'abort' but computes it with
+-- 'System.IO.Unsafe.unsafePerformIO'.
+abortPurely :: StatusCode → [ (String, String) ] → Maybe String → a
+abortPurely = ((unsafePerformIO .) .) . abort
-- |Computation of @'abortSTM' status headers msg@ just computes
-- 'abort' in a 'Control.Monad.STM.STM' monad.
-abortSTM :: StatusCode -> [ (String, String) ] -> Maybe String -> STM a
+abortSTM :: StatusCode → [ (String, String) ] → Maybe String → STM a
abortSTM status headers msg
= status `seq` headers `seq` msg `seq`
unsafeIOToSTM $! abort status headers msg
-- | Computation of @'abortA' -< (status, (headers, msg))@ just
-- computes 'abort' in an 'Control.Arrow.ArrowIO.ArrowIO'.
-abortA :: ArrowIO a => a (StatusCode, ([ (String, String) ], Maybe String)) c
+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 を使ってデフォルトのメッセージを得な
-- ければならない。
-abortPage :: Config -> Maybe Request -> Response -> Abortion -> String
+abortPage :: Config → Maybe Request → Response → Abortion → String
abortPage conf reqM res abo
= conf `seq` reqM `seq` res `seq` abo `seq`
case aboMessage abo of
Just msg
- -> let [html] = unsafePerformIO
+ → let [html] = unsafePerformIO
$ runX ( mkDefaultPage conf (aboStatus abo) (txt msg)
>>>
- writeDocumentToString [(a_indent, v_1)]
+ writeDocumentToString [ withIndent True ]
)
in
html
Nothing
- -> let res' = res { resStatus = aboStatus abo }
+ → let res' = res { resStatus = aboStatus abo }
res'' = foldl (.) id [setHeader name value
- | (name, value) <- aboHeaders abo]
- $ res'
+ | (name, value) <- fromHeaders $ aboHeaders abo] res'
in
getDefaultPage conf reqM res''