]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Resource.hs
use time-http 0.5
[Lucu.git] / Network / HTTP / Lucu / Resource.hs
index 8585ceaf29ce993f6a1a002ed41c61d3f5c18f1e..520502204df5d933484d85298115051574915dd3 100644 (file)
@@ -8,6 +8,7 @@
   , QuasiQuotes
   , RecordWildCards
   , UnicodeSyntax
+  , ViewPatterns
   #-}
 -- |This is the Resource Monad; monadic actions to define a behavior
 -- of resource. The 'Rsrc' Monad is a kind of 'IO' Monad thus it
@@ -158,11 +159,11 @@ import Data.Collections
 import Data.Convertible.Base
 import Data.Convertible.Instances.Text ()
 import Data.Convertible.Utils
+import Data.Default
 import Data.List (intersperse, sort)
 import Data.Maybe
 import Data.Monoid
 import Data.Monoid.Unicode
-import Data.Proxy
 import Data.Tagged
 import Data.Text (Text)
 import Data.Time
@@ -180,9 +181,8 @@ import Network.HTTP.Lucu.Parser
 import Network.HTTP.Lucu.Request
 import Network.HTTP.Lucu.Resource.Internal
 import Network.HTTP.Lucu.Response
-import Network.HTTP.Lucu.MIMEType (MIMEType(..))
-import qualified Network.HTTP.Lucu.MIMEType as MT
-import Network.HTTP.Lucu.MIMEType.TH
+import Network.HTTP.Lucu.Response.StatusCode
+import Network.HTTP.Lucu.MIMEType
 import Network.HTTP.Lucu.Utils
 import Network.Socket hiding (accept)
 import Network.URI hiding (path)
@@ -265,7 +265,7 @@ getAccept
            Nothing
                → return []
            Just accept
-               → case P.parseOnly (finishOff MT.mimeTypeList) (cs accept) of
+               → case P.parseOnly (finishOff def) (cs accept) of
                     Right xs → return xs
                     Left  _  → abort $ mkAbortion' BadRequest
                                      $ "Unparsable Accept: " ⊕ cs accept
@@ -293,7 +293,7 @@ getAcceptEncoding
                       -- identity のみが許される。
                       return [("identity", Nothing)]
                  else
-                     case P.parseOnly (finishOff acceptEncodingList) (cs ae) of
+                     case P.parseOnly (finishOff def) (cs ae) of
                        Right xs → return $ map toTuple $ reverse $ sort xs
                        Left  _  → abort $ mkAbortion' BadRequest
                                         $ "Unparsable Accept-Encoding: " ⊕ cs ae
@@ -317,7 +317,7 @@ getContentType
            Nothing
                → return Nothing
            Just cType
-               → case P.parseOnly (finishOff MT.mimeType) (cs cType) of
+               → case P.parseOnly (finishOff def) (cs cType) of
                     Right t → return $ Just t
                     Left  _ → abort $ mkAbortion' BadRequest
                                     $ "Unparsable Content-Type: " ⊕ cs cType
@@ -331,7 +331,7 @@ getAuthorization
            Nothing
                → return Nothing
            Just auth
-               → case P.parseOnly (finishOff authCredential) (cs auth) of
+               → case P.parseOnly (finishOff def) (cs auth) of
                     Right ac → return $ Just ac
                     Left  _  → return Nothing
 
@@ -356,8 +356,7 @@ foundEntity tag timeStamp
          method ← getMethod
          when (method ≡ GET ∨ method ≡ HEAD)
              $ setHeader "Last-Modified"
-             $ flip proxy http
-             $ cs timeStamp
+             $ formatUTCTime timeStamp
          when (method ≡ POST)
              $ abort
              $ mkAbortion' InternalServerError
@@ -394,7 +393,10 @@ foundETag tag
                → if value ≡ "*" then
                       return ()
                   else
-                      case P.parseOnly (finishOff eTagList) (cs value) of
+                      case P.parseOnly (finishOff def) (cs value) of
+                        Right []
+                            → abort $ mkAbortion' BadRequest
+                                    $ "Empty If-Match"
                         Right tags
                             -- tags の中に一致するものが無ければ
                             -- PreconditionFailed で終了。
@@ -422,7 +424,10 @@ foundETag tag
                       abort $ mkAbortion' statusForNoneMatch
                             $ "The entity tag matches: *"
                   else
-                      case P.parseOnly (finishOff eTagList) (cs value) of
+                      case P.parseOnly (finishOff def) (cs value) of
+                        Right []
+                            → abort $ mkAbortion' BadRequest
+                                    $ "Empty If-None-Match"
                         Right tags
                             → when (any (≡ tag) tags)
                                   $ abort
@@ -451,8 +456,7 @@ foundTimeStamp timeStamp
          method ← getMethod
          when (method ≡ GET ∨ method ≡ HEAD)
              $ setHeader "Last-Modified"
-             $ flip proxy http
-             $ cs timeStamp
+             $ formatUTCTime timeStamp
          when (method ≡ POST)
              $ abort
              $ mkAbortion' InternalServerError
@@ -466,7 +470,7 @@ foundTimeStamp timeStamp
 
          ifModSince ← getHeader "If-Modified-Since"
          case ifModSince of
-           Just str → case fromAttempt $ ca (Tagged str ∷ Tagged HTTP Ascii) of
+           Just str → case untag' <$> (fromAttempt $ ca str) of
                          Just lastTime
                              → when (timeStamp ≤ lastTime)
                                $ abort
@@ -479,7 +483,7 @@ foundTimeStamp timeStamp
 
          ifUnmodSince ← getHeader "If-Unmodified-Since"
          case ifUnmodSince of
-           Just str → case fromAttempt $ ca (Tagged str ∷ Tagged HTTP Ascii) of
+           Just str → case untag' <$> (fromAttempt $ ca str) of
                          Just lastTime
                              → when (timeStamp > lastTime)
                                $ abort
@@ -491,6 +495,10 @@ foundTimeStamp timeStamp
            Nothing  → return ()
 
          driftTo ReceivingBody
+    where
+      untag' ∷ Tagged HTTP α → α
+      {-# INLINE untag' #-}
+      untag' = untag
 
 -- |@'foundNoEntity' mStr@ tells the system that the 'Rsrc' found no
 -- entity for the request URI. @mStr@ is an optional error message to
@@ -618,13 +626,13 @@ getForm limit
 -- \"Location\" header field as @uri@. The @code@ must satisfy
 -- 'isRedirection' or it raises an error.
 redirect ∷ StatusCode sc ⇒ sc → URI → Rsrc ()
-redirect sc uri
-    = do when (sc â\89\88 NotModified ∨ (¬) (isRedirection sc))
+redirect (fromStatusCode → sc) uri
+    = do when (sc â\89¡ cs NotModified ∨ (¬) (isRedirection sc))
              $ abort
              $ mkAbortion' InternalServerError
              $ cs
              $ ("Attempted to redirect with status " ∷ Ascii)
-             ⊕ cs (fromStatusCode sc)
+             ⊕ cs sc
          setStatus sc
          setLocation uri