-- | -- -- Since 3.0.4 module Network.Wai.Middleware.StreamFile (streamFile) where import Network.Wai (responseStream) import Network.Wai.Internal import Network.Wai (Middleware, responseToStream) import qualified Data.ByteString.Char8 as S8 import System.PosixCompat (getFileStatus, fileSize, FileOffset) import Network.HTTP.Types (hContentLength) -- |Convert ResponseFile type responses into ResponseStream type -- -- Checks the response type, and if it's a ResponseFile, converts it -- into a ResponseStream. Other response types are passed through -- unchanged. -- -- Converted responses get a Content-Length header. -- -- Streaming a file will bypass a sendfile system call, and may be -- useful to work around systems without working sendfile -- implementations. -- -- Since 3.0.4 streamFile :: Middleware streamFile app env sendResponse = app env $ \res -> case res of ResponseFile _ _ fp _ -> withBody sendBody where (s, hs, withBody) = responseToStream res sendBody :: StreamingBody -> IO ResponseReceived sendBody body = do len <- getFileSize fp let hs' = (hContentLength, (S8.pack (show len))) : hs sendResponse $ responseStream s hs' body _ -> sendResponse res getFileSize :: FilePath -> IO FileOffset getFileSize path = do stat <- getFileStatus path return (fileSize stat)