X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Rakka%2FResource.hs;h=26d73897e544cc1ec13d3553913bff5bf214da15;hb=443af4d3304139bb2187a0c726327b9c05829810;hp=e1166b4d33079b0096d81a63f2d8c00af1d8b396;hpb=885faf1cabc3f79c90e1885268e2a9138b1ddefb;p=Rakka.git diff --git a/Rakka/Resource.hs b/Rakka/Resource.hs index e1166b4..26d7389 100644 --- a/Rakka/Resource.hs +++ b/Rakka/Resource.hs @@ -1,6 +1,9 @@ module Rakka.Resource ( runIdempotentA + , runXmlA + , getEntityType , outputXmlPage + , getUserID ) where @@ -10,18 +13,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 +64,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 @@ -73,6 +138,7 @@ outputXmlPage tree toXHTML let formatter = case mType of MIMEType "application" "xhtml+xml" _ -> toXHTML MIMEType "text" "xml" _ -> this + _ -> undefined [resultStr] <- liftIO $ runX ( setErrorMsgHandler False fail >>> constA tree @@ -81,4 +147,17 @@ outputXmlPage tree toXHTML >>> writeDocumentToString [ (a_indent, v_1) ] ) - output resultStr \ No newline at end of file + output resultStr + + +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