]> gitweb @ CieloNegro.org - Rakka.git/blobdiff - Rakka/Resource.hs
improvements related to RSS feed
[Rakka.git] / Rakka / Resource.hs
index e1166b4d33079b0096d81a63f2d8c00af1d8b396..d0d9c4866d06665732ab91344ed96dc87dc2ac2a 100644 (file)
@@ -1,6 +1,10 @@
 module Rakka.Resource
     ( runIdempotentA
+    , runXmlA
+    , getEntityType
     , outputXmlPage
+    , outputXmlPage'
+    , getUserID
     )
     where
 
@@ -10,18 +14,27 @@ import           Control.Monad
 import           Control.Monad.Trans
 import           Network.HTTP.Lucu
 import           Network.HTTP.Lucu.Utils
-import           Network.URI
+import           Network.URI hiding (path)
+import           Rakka.Authorization
+import           Rakka.Environment
+import           Rakka.Validation
+import           System.Log.Logger
+import           Text.XML.HXT.Arrow.ReadDocument
 import           Text.XML.HXT.Arrow.WriteDocument
 import           Text.XML.HXT.Arrow.XmlIOStateArrow
 import           Text.XML.HXT.DOM.TypeDefs
 import           Text.XML.HXT.DOM.XmlKeywords
 
 
--- /         ==> /
--- /foo      ==> /foo.html
--- /foo/     ==> /foo.html
--- /foo.bar/ ==> /foo.bar
--- /foo.bar  ==> /foo.bar
+logger :: String
+logger = "Rakka.Resource"
+
+
+-- "/"         ==> "/"
+-- "/foo"      ==> "/foo.html"
+-- "/foo/"     ==> "/foo.html"
+-- "/foo.bar/" ==> "/foo.bar"
+-- "/foo.bar"  ==> "/foo.bar"
 canonicalizeURI :: Resource ()
 canonicalizeURI 
     = do uri <- getRequestURI
@@ -52,6 +65,59 @@ runIdempotentA a
          rsrc
 
 
+runXmlA :: Environment -> FilePath -> IOSArrow XmlTree (Resource c) -> Resource c
+runXmlA env schemaPath a
+    = do inputA <- getInputXmlA env schemaPath
+         [rsrc] <- liftIO $ runX ( inputA
+                                   >>>
+                                   setErrorMsgHandler False fail
+                                   >>>
+                                   a
+                                 )
+         rsrc
+
+
+-- well-formed でない時は 400 Bad Request になり、valid でない時は 422
+-- Unprocessable Entity になる。入力の型が XML でない時は 415
+-- Unsupported Media Type を返す。
+getInputXmlA :: Environment -> FilePath -> Resource (IOSArrow b XmlTree)
+getInputXmlA env schemaPath
+    = do reader    <- getInputReader
+         validator <- getValidator env schemaPath
+         return ( setErrorMsgHandler False (abort BadRequest [] . Just)
+                  >>>
+                  reader
+                  >>>
+                  setErrorMsgHandler False (abort UnprocessableEntitiy [] . Just)
+                  >>>
+                  validator
+                )
+
+
+getInputReader :: Resource (IOSArrow b XmlTree)
+getInputReader 
+    = do mimeType <- getContentType
+         case mimeType of
+           Nothing
+               -> getFailingReader BadRequest [] (Just "Missing Content-Type")
+           Just (MIMEType "text" "xml" _)
+               -> getXmlReader
+           Just (MIMEType "application" "xml" _)
+               -> getXmlReader
+           Just t
+               -> getFailingReader UnsupportedMediaType [] (Just $ "Unsupported media type: " ++ show t)
+    where
+      getXmlReader
+          = do req <- input defaultLimit
+               liftIO $ debugM logger req
+               return $ readString [ (a_validate         , v_0)
+                                   , (a_check_namespaces , v_1)
+                                   , (a_remove_whitespace, v_0)
+                                   ] req
+      getFailingReader code headers msg
+          = return $ proc _ -> abortA -< (code, (headers, msg))
+
+
 getEntityType :: Resource MIMEType
 getEntityType
     = do uri <- getRequestURI
@@ -62,17 +128,18 @@ getEntityType
     where
       extMap :: [(String, MIMEType)]
       extMap = [ ("html", read "application/xhtml+xml")
+               , ( "rdf", read "application/rss+xml"  )
                , ( "xml", read "text/xml"             )
                ]
 
 
-outputXmlPage :: XmlTree -> IOSArrow XmlTree XmlTree -> Resource ()
-outputXmlPage tree toXHTML
+outputXmlPage :: XmlTree -> [(MIMEType, IOSArrow XmlTree XmlTree)] -> Resource ()
+outputXmlPage tree formatters
     = do mType <- getEntityType
          setContentType mType
-         let formatter = case mType of
-                           MIMEType "application" "xhtml+xml" _ -> toXHTML
-                           MIMEType "text"        "xml"       _ -> this
+         let formatter = case lookup mType formatters of
+                           Just f  -> f
+                           Nothing -> this
          [resultStr] <- liftIO $ runX ( setErrorMsgHandler False fail
                                         >>>
                                         constA tree
@@ -81,4 +148,22 @@ outputXmlPage tree toXHTML
                                         >>>
                                         writeDocumentToString [ (a_indent, v_1) ]
                                       )
-         output resultStr
\ No newline at end of file
+         output resultStr
+
+
+outputXmlPage' :: XmlTree -> IOSArrow XmlTree XmlTree -> Resource ()
+outputXmlPage' tree toXHTML
+    = outputXmlPage tree [(MIMEType "application" "xhtml+xml" [], toXHTML)]
+
+
+getUserID :: Environment -> Resource (Maybe String)
+getUserID env
+    = do auth <- getAuthorization
+         case auth of
+           Just (BasicAuthCredential userID password)
+               -> do valid <- isValidPair (envAuthDB env) userID password
+                     if valid then
+                         return (Just userID)
+                       else
+                         return Nothing
+           _   -> return Nothing