X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FResource.hs;h=b478503c8bc53d6af8b74e6b9cf196350b1772c2;hp=0ff5081a63dbda5c759fa18a00fb9685fdaf730c;hb=0678be8;hpb=3baf479eba12bc3e9c4ef966df770cd70aa5cd81 diff --git a/Network/HTTP/Lucu/Resource.hs b/Network/HTTP/Lucu/Resource.hs index 0ff5081..b478503 100644 --- a/Network/HTTP/Lucu/Resource.hs +++ b/Network/HTTP/Lucu/Resource.hs @@ -149,19 +149,23 @@ import Control.Monad.IO.Class import Control.Monad.Unicode import Data.Ascii (Ascii, CIAscii) import qualified Data.Ascii as A +import Data.Attempt import qualified Data.Attoparsec.Char8 as P import Data.ByteString (ByteString) import qualified Data.ByteString as Strict import qualified Data.ByteString.Lazy as Lazy import Data.Collections +import Data.Convertible.Base 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 qualified Data.Text as T import Data.Time -import qualified Data.Time.HTTP as HTTP +import Data.Time.Format.HTTP import Network.HTTP.Lucu.Abortion import Network.HTTP.Lucu.Authentication import Network.HTTP.Lucu.Config @@ -212,9 +216,8 @@ getRequestVersion ∷ Rsrc HttpVersion getRequestVersion = reqVersion <$> getRequest -- |This is an analogy of CGI PATH_INFO. 'getPathInfo' always returns --- @[]@ if the corresponding --- 'Network.HTTP.Lucu.Resource.Tree.Resource' is not greedy. See: --- 'getResourcePath' +-- @[]@ if the corresponding 'Resource' is not greedy. See +-- 'getResourcePath'. -- -- Note that the returned path components are URI-decoded. getPathInfo ∷ Rsrc [Strict.ByteString] @@ -352,7 +355,9 @@ foundEntity tag timeStamp method ← getMethod when (method ≡ GET ∨ method ≡ HEAD) - $ setHeader "Last-Modified" (HTTP.toAscii timeStamp) + $ setHeader "Last-Modified" + $ flip proxy http + $ cs timeStamp when (method ≡ POST) $ abort $ mkAbortion' InternalServerError @@ -375,7 +380,7 @@ foundETag tag when (method ≡ GET ∨ method ≡ HEAD) $ setHeader "ETag" $ A.fromAsciiBuilder - $ printETag tag + $ cs tag when (method ≡ POST) $ abort $ mkAbortion' InternalServerError @@ -446,7 +451,9 @@ foundTimeStamp timeStamp method ← getMethod when (method ≡ GET ∨ method ≡ HEAD) - $ setHeader "Last-Modified" (HTTP.toAscii timeStamp) + $ setHeader "Last-Modified" + $ flip proxy http + $ cs timeStamp when (method ≡ POST) $ abort $ mkAbortion' InternalServerError @@ -460,28 +467,28 @@ foundTimeStamp timeStamp ifModSince ← getHeader "If-Modified-Since" case ifModSince of - Just str → case HTTP.fromAscii str of - Right lastTime + Just str → case fromAttempt $ ca (Tagged str ∷ Tagged HTTP Ascii) of + Just lastTime → when (timeStamp ≤ lastTime) $ abort $ mkAbortion' statusForIfModSince $ "The entity has not been modified since " ⊕ A.toText str - Left e + Nothing → abort $ mkAbortion' BadRequest - $ "Malformed If-Modified-Since: " ⊕ T.pack e + $ "Malformed If-Modified-Since: " ⊕ A.toText str Nothing → return () ifUnmodSince ← getHeader "If-Unmodified-Since" case ifUnmodSince of - Just str → case HTTP.fromAscii str of - Right lastTime + Just str → case fromAttempt $ ca (Tagged str ∷ Tagged HTTP Ascii) of + Just lastTime → when (timeStamp > lastTime) $ abort $ mkAbortion' PreconditionFailed $ "The entity has not been modified since " ⊕ A.toText str - Left e + Nothing → abort $ mkAbortion' BadRequest - $ "Malformed If-Unmodified-Since: " ⊕ T.pack e + $ "Malformed If-Unmodified-Since: " ⊕ A.toText str Nothing → return () driftTo ReceivingBody @@ -580,10 +587,9 @@ getForm limit → readMultipartFormData params Just cType → abort $ mkAbortion' UnsupportedMediaType - $ A.toText - $ A.fromAsciiBuilder - $ A.toAsciiBuilder "Unsupported media type: " - ⊕ MT.printMIMEType cType + $ cs + $ ("Unsupported media type: " ∷ Ascii) + ⊕ cs cType where readWWWFormURLEncoded = (map toPairWithFormData ∘ parseWWWFormURLEncoded) @@ -628,8 +634,7 @@ redirect sc uri -- \"Content-Type\" as @mType@. Declaring \"Content-Type\" is -- mandatory for sending a response body. setContentType ∷ MIMEType → Rsrc () -setContentType - = setHeader "Content-Type" ∘ A.fromAsciiBuilder ∘ MT.printMIMEType +setContentType = setHeader "Content-Type" ∘ cs -- |@'setLocation' uri@ declares the response header \"Location\" as -- @uri@. You usually don't need to call this function directly. @@ -663,11 +668,11 @@ setContentEncoding codings -- |@'setWWWAuthenticate' challenge@ declares the response header -- \"WWW-Authenticate\" as @challenge@. setWWWAuthenticate ∷ AuthChallenge → Rsrc () -setWWWAuthenticate = setHeader "WWW-Authenticate" ∘ printAuthChallenge +setWWWAuthenticate = setHeader "WWW-Authenticate" ∘ cs -- |Write a chunk in 'Strict.ByteString' to the response body. You -- must first declare the response header \"Content-Type\" before --- applying this function. See: 'setContentType' +-- applying this function. See 'setContentType'. putChunk ∷ Strict.ByteString → Rsrc () putChunk = putBuilder ∘ BB.fromByteString @@ -675,7 +680,7 @@ putChunk = putBuilder ∘ BB.fromByteString -- can be safely applied to an infinitely long 'Lazy.ByteString'. -- -- Note that you must first declare the response header --- \"Content-Type\" before applying this function. See: --- 'setContentType' +-- \"Content-Type\" before applying this function. See +-- 'setContentType'. putChunks ∷ Lazy.ByteString → Rsrc () putChunks = putBuilder ∘ BB.fromLazyByteString