-- in any 'Prelude.IO' monads or arrows.
module Network.HTTP.Lucu.Abortion
( Abortion(..)
+
, abort
, abortPurely
, abortSTM
, abortPage
)
where
-import Control.Arrow
+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 Data.Ascii (Ascii, CIAscii)
import Data.Text (Text)
import qualified Data.Text as T
-import qualified Data.Text.Lazy as Lazy
import Data.Typeable
import Network.HTTP.Lucu.Config
import Network.HTTP.Lucu.DefaultPage
import Text.XML.HXT.Arrow.XmlState
data Abortion = Abortion {
- aboStatus :: !StatusCode
- , aboHeaders :: !Headers
- , aboMessage :: !(Maybe Text)
+ aboStatus ∷ !StatusCode
+ , aboHeaders ∷ !Headers
+ , aboMessage ∷ !(Maybe Text)
} deriving (Eq, Show, Typeable)
instance Exception Abortion
-- 'Network.HTTP.Lucu.Resource.Resource' monad with given status,
-- additional response headers, and optional message string.
--
--- What this really does is to throw a special
--- 'Control.Exception.Exception'. The exception will be caught by the
--- Lucu system.
+-- 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
--
-- 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 → [ (CIAscii, Ascii) ] → Maybe Text → m a
+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 computes it with
-- 'System.IO.Unsafe.unsafePerformIO'.
-abortPurely :: StatusCode → [ (CIAscii, Ascii) ] → Maybe Text → a
+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 → [ (CIAscii, Ascii) ] → Maybe Text → STM a
+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 :: Arrow (⇝) ⇒ (StatusCode, ([ (CIAscii, Ascii) ], Maybe Text)) ⇝ c
+abortA ∷ ArrowIO (⇝) ⇒ (StatusCode, ([ (CIAscii, Ascii) ], Maybe Text)) ⇝ c
{-# INLINE abortA #-}
abortA = proc (status, (headers, msg)) →
- returnA ⤙ abortPurely status headers msg
+ arrIO throwIO ⤙ Abortion status (toHeaders headers) msg
-- aboMessage が Just なら單に mkDefaultPage に渡すだけで良いので樂だが、
-- Nothing の場合は getDefaultPage を使ってデフォルトのメッセージを得な
-- ければならない。
-abortPage :: Config → Maybe Request → Response → Abortion → Lazy.Text
+abortPage ∷ Config → Maybe Request → Response → Abortion → Builder
abortPage conf reqM res abo
= case aboMessage abo of
Just msg
writeDocumentToString [ withIndent True ]
) ()
in
- Lazy.pack html
+ BB.fromString html
Nothing
→ let res' = res { resStatus = aboStatus abo }
res'' = foldl (∘) id [setHeader name value