From 1718c5bf1e0ff2c28d46ee793756596c75ed2348 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Sat, 25 Dec 2010 20:49:47 +0200 Subject: [PATCH] Including content length field for ContentBuilder --- Yesod/Content.hs | 20 ++++++++++++-------- Yesod/Dispatch.hs | 9 ++++++++- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Yesod/Content.hs b/Yesod/Content.hs index 74f044ed..7a7bd274 100644 --- a/Yesod/Content.hs +++ b/Yesod/Content.hs @@ -53,7 +53,7 @@ module Yesod.Content import Data.Maybe (mapMaybe) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L -import Data.Text.Lazy (Text) +import Data.Text.Lazy (Text, pack) import qualified Data.Text as T import Data.Time @@ -76,33 +76,37 @@ import Data.Monoid (mempty) import Text.Hamlet (Html) import Text.Blaze.Renderer.Utf8 (renderHtmlBuilder) -data Content = ContentBuilder Builder +data Content = ContentBuilder Builder (Maybe Int) -- ^ The content and optional content length. | ContentEnum (forall a. Enumerator Builder IO a) | ContentFile FilePath -- | Zero-length enumerator. emptyContent :: Content -emptyContent = ContentBuilder mempty +emptyContent = ContentBuilder mempty $ Just 0 -- | Anything which can be converted into 'Content'. Most of the time, you will --- want to use the 'ContentEnum' constructor. An easier approach will be to use +-- want to use the 'ContentBuilder' constructor. An easier approach will be to use -- a pre-defined 'toContent' function, such as converting your data into a lazy -- bytestring and then calling 'toContent' on that. +-- +-- Please note that the built-in instances for lazy data structures ('String', +-- lazy 'L.ByteString', lazy 'Text' and 'Html') will not automatically include +-- the content length for the 'ContentBuilder' constructor. class ToContent a where toContent :: a -> Content instance ToContent B.ByteString where - toContent = ContentBuilder . fromByteString + toContent bs = ContentBuilder (fromByteString bs) $ Just $ B.length bs instance ToContent L.ByteString where - toContent = ContentBuilder . fromLazyByteString + toContent = flip ContentBuilder Nothing . fromLazyByteString instance ToContent T.Text where toContent = toContent . Data.Text.Encoding.encodeUtf8 instance ToContent Text where toContent = toContent . Data.Text.Lazy.Encoding.encodeUtf8 instance ToContent String where - toContent = toContent . T.pack + toContent = toContent . pack instance ToContent Html where - toContent = ContentBuilder . renderHtmlBuilder + toContent bs = ContentBuilder (renderHtmlBuilder bs) Nothing -- | A function which gives targetted representations of content based on the -- content-types the user accepts. diff --git a/Yesod/Dispatch.hs b/Yesod/Dispatch.hs index 7086e673..d782a2d3 100644 --- a/Yesod/Dispatch.hs +++ b/Yesod/Dispatch.hs @@ -339,7 +339,14 @@ toWaiApp' y key' segments env = do hs''' = ("Content-Type", charsToBs ct) : hs'' return $ case c of - ContentBuilder b -> W.responseBuilder s hs''' b + ContentBuilder b mlen -> + let hs'''' = + case mlen of + Nothing -> hs''' + Just len -> + ("Content-Length", B.pack $ show len) + : hs''' + in W.responseBuilder s hs'''' b ContentFile fp -> W.ResponseFile s hs''' fp ContentEnum e -> W.ResponseEnumerator $ \iter -> run_ $ e $$ iter s hs'''