sendFilePart
This commit is contained in:
parent
b1abfd1a6a
commit
35e424f241
@ -61,10 +61,11 @@ import Data.Monoid (mempty)
|
|||||||
import Text.Hamlet (Html)
|
import Text.Hamlet (Html)
|
||||||
import Text.Blaze.Renderer.Utf8 (renderHtmlBuilder)
|
import Text.Blaze.Renderer.Utf8 (renderHtmlBuilder)
|
||||||
import Data.String (IsString (fromString))
|
import Data.String (IsString (fromString))
|
||||||
|
import Network.Wai (FilePart)
|
||||||
|
|
||||||
data Content = ContentBuilder Builder (Maybe Int) -- ^ The content and optional content length.
|
data Content = ContentBuilder Builder (Maybe Int) -- ^ The content and optional content length.
|
||||||
| ContentEnum (forall a. Enumerator Builder IO a)
|
| ContentEnum (forall a. Enumerator Builder IO a)
|
||||||
| ContentFile FilePath
|
| ContentFile FilePath (Maybe FilePart)
|
||||||
|
|
||||||
-- | Zero-length enumerator.
|
-- | Zero-length enumerator.
|
||||||
emptyContent :: Content
|
emptyContent :: Content
|
||||||
|
|||||||
@ -195,7 +195,7 @@ class RenderRoute (Route a) => Yesod a where
|
|||||||
-- be the inverse of 'splitPath'.
|
-- be the inverse of 'splitPath'.
|
||||||
joinPath :: a
|
joinPath :: a
|
||||||
-> Builder -- ^ application root
|
-> Builder -- ^ application root
|
||||||
-> [TS.Text] -- ^ path pieces FIXME Text
|
-> [TS.Text] -- ^ path pieces
|
||||||
-> [(TS.Text, TS.Text)] -- ^ query string
|
-> [(TS.Text, TS.Text)] -- ^ query string
|
||||||
-> Builder
|
-> Builder
|
||||||
joinPath _ ar pieces qs' = ar `mappend` encodePath pieces qs
|
joinPath _ ar pieces qs' = ar `mappend` encodePath pieces qs
|
||||||
@ -407,7 +407,6 @@ widgetToPageContent (GWidget w) = do
|
|||||||
let title = maybe mempty unTitle mTitle
|
let title = maybe mempty unTitle mTitle
|
||||||
let scripts = runUniqueList scripts'
|
let scripts = runUniqueList scripts'
|
||||||
let stylesheets = runUniqueList stylesheets'
|
let stylesheets = runUniqueList stylesheets'
|
||||||
-- FIXME check size of cassius/julius template
|
|
||||||
let cssToHtml = preEscapedLazyText . renderCss
|
let cssToHtml = preEscapedLazyText . renderCss
|
||||||
celper :: Cassius url -> Hamlet url
|
celper :: Cassius url -> Hamlet url
|
||||||
celper = fmap cssToHtml
|
celper = fmap cssToHtml
|
||||||
|
|||||||
@ -50,6 +50,7 @@ module Yesod.Handler
|
|||||||
, invalidArgs
|
, invalidArgs
|
||||||
-- ** Short-circuit responses.
|
-- ** Short-circuit responses.
|
||||||
, sendFile
|
, sendFile
|
||||||
|
, sendFilePart
|
||||||
, sendResponse
|
, sendResponse
|
||||||
, sendResponseStatus
|
, sendResponseStatus
|
||||||
, sendResponseCreated
|
, sendResponseCreated
|
||||||
@ -280,7 +281,7 @@ data YesodAppResult
|
|||||||
data HandlerContents =
|
data HandlerContents =
|
||||||
HCContent H.Status ChooseRep
|
HCContent H.Status ChooseRep
|
||||||
| HCError ErrorResponse
|
| HCError ErrorResponse
|
||||||
| HCSendFile ContentType FilePath -- FIXME replace FilePath with opaque type from system-filepath?
|
| HCSendFile ContentType FilePath (Maybe W.FilePart) -- FIXME replace FilePath with opaque type from system-filepath?
|
||||||
| HCRedirect RedirectType Text
|
| HCRedirect RedirectType Text
|
||||||
| HCCreated Text
|
| HCCreated Text
|
||||||
| HCWai W.Response
|
| HCWai W.Response
|
||||||
@ -383,8 +384,8 @@ runHandler handler mrender sroute tomr ma sa =
|
|||||||
let hs' = headers hs
|
let hs' = headers hs
|
||||||
in return $ YARPlain (getStatus e) hs' ct c sess
|
in return $ YARPlain (getStatus e) hs' ct c sess
|
||||||
YARWai _ -> return yar
|
YARWai _ -> return yar
|
||||||
let sendFile' ct fp =
|
let sendFile' ct fp p =
|
||||||
return $ YARPlain H.status200 (headers []) ct (ContentFile fp) finalSession
|
return $ YARPlain H.status200 (headers []) ct (ContentFile fp p) finalSession
|
||||||
case contents of
|
case contents of
|
||||||
HCContent status a -> do
|
HCContent status a -> do
|
||||||
(ct, c) <- liftIO $ chooseRep a cts
|
(ct, c) <- liftIO $ chooseRep a cts
|
||||||
@ -395,8 +396,8 @@ runHandler handler mrender sroute tomr ma sa =
|
|||||||
return $ YARPlain
|
return $ YARPlain
|
||||||
(getRedirectStatus rt) hs typePlain emptyContent
|
(getRedirectStatus rt) hs typePlain emptyContent
|
||||||
finalSession
|
finalSession
|
||||||
HCSendFile ct fp -> catchIter
|
HCSendFile ct fp p -> catchIter
|
||||||
(sendFile' ct fp)
|
(sendFile' ct fp p)
|
||||||
(handleError . toErrorHandler)
|
(handleError . toErrorHandler)
|
||||||
HCCreated loc -> do
|
HCCreated loc -> do
|
||||||
let hs = Header "Location" (encodeUtf8 loc) : headers []
|
let hs = Header "Location" (encodeUtf8 loc) : headers []
|
||||||
@ -510,7 +511,17 @@ getMessage = do
|
|||||||
-- For some backends, this is more efficient than reading in the file to
|
-- For some backends, this is more efficient than reading in the file to
|
||||||
-- memory, since they can optimize file sending via a system call to sendfile.
|
-- memory, since they can optimize file sending via a system call to sendfile.
|
||||||
sendFile :: Monad mo => ContentType -> FilePath -> GGHandler sub master mo a
|
sendFile :: Monad mo => ContentType -> FilePath -> GGHandler sub master mo a
|
||||||
sendFile ct = GHandler . lift . throwError . HCSendFile ct
|
sendFile ct fp = GHandler . lift . throwError $ HCSendFile ct fp Nothing
|
||||||
|
|
||||||
|
-- | Same as 'sendFile', but only sends part of a file.
|
||||||
|
sendFilePart :: Monad mo
|
||||||
|
=> ContentType
|
||||||
|
-> FilePath
|
||||||
|
-> Integer -- ^ offset
|
||||||
|
-> Integer -- ^ count
|
||||||
|
-> GGHandler sub master mo a
|
||||||
|
sendFilePart ct fp off count =
|
||||||
|
GHandler . lift . throwError $ HCSendFile ct fp $ Just $ W.FilePart off count
|
||||||
|
|
||||||
-- | Bypass remaining handler code and output the given content with a 200
|
-- | Bypass remaining handler code and output the given content with a 200
|
||||||
-- status code.
|
-- status code.
|
||||||
@ -688,7 +699,7 @@ yarToResponse renderHeaders (YARPlain s hs ct c sessionFinal) =
|
|||||||
ContentBuilder b mlen ->
|
ContentBuilder b mlen ->
|
||||||
let hs' = maybe finalHeaders finalHeaders' mlen
|
let hs' = maybe finalHeaders finalHeaders' mlen
|
||||||
in W.ResponseBuilder s hs' b
|
in W.ResponseBuilder s hs' b
|
||||||
ContentFile fp -> W.ResponseFile s finalHeaders fp Nothing -- FIXME handle partial files
|
ContentFile fp p -> W.ResponseFile s finalHeaders fp p
|
||||||
ContentEnum e ->
|
ContentEnum e ->
|
||||||
W.ResponseEnumerator $ \iter -> run_ $ e $$ iter s finalHeaders
|
W.ResponseEnumerator $ \iter -> run_ $ e $$ iter s finalHeaders
|
||||||
where
|
where
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user