packages feed

wai-app-file-cgi 0.2.2 → 0.2.3

raw patch · 5 files changed

+53/−59 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Network.Wai.Application.Classic: FileInfo :: FilePath -> Integer -> HTTPDate -> FileInfo
+ Network.Wai.Application.Classic: data FileInfo
+ Network.Wai.Application.Classic: fileInfoName :: FileInfo -> FilePath
+ Network.Wai.Application.Classic: fileInfoSize :: FileInfo -> Integer
+ Network.Wai.Application.Classic: fileInfoTime :: FileInfo -> HTTPDate
+ Network.Wai.Application.Classic: getFileInfo :: AppSpec -> ByteString -> IO (Maybe FileInfo)
- Network.Wai.Application.Classic: AppSpec :: ByteString -> ByteString -> (ByteString -> Bool) -> (Request -> Status -> Maybe Integer -> IO ()) -> AppSpec
+ Network.Wai.Application.Classic: AppSpec :: ByteString -> ByteString -> (ByteString -> Bool) -> (Request -> Status -> Maybe Integer -> IO ()) -> (ByteString -> IO (Maybe FileInfo)) -> AppSpec

Files

Network/Wai/Application/Classic.hs view
@@ -5,6 +5,7 @@ module Network.Wai.Application.Classic (   -- * Types     AppSpec(..)+  , FileInfo(..)   -- * Files   , FileRoute(..), fileApp   -- * CGI
Network/Wai/Application/Classic/File.hs view
@@ -7,7 +7,7 @@ import Control.Monad.IO.Class (liftIO) import Data.ByteString (ByteString) import qualified Data.ByteString as BS hiding (unpack, pack)-import qualified Data.ByteString.Char8 as BS (unpack, pack)+import qualified Data.ByteString.Char8 as BS (pack) import qualified Data.ByteString.Lazy.Char8 as BL (length) import Network.HTTP.Types import Network.Wai@@ -41,8 +41,8 @@ fileApp :: AppSpec -> FileRoute -> Application fileApp spec filei req = do     RspSpec st hdr body <- case method of-        "GET"  -> processGET  req file ishtml rfile-        "HEAD" -> processHEAD req file ishtml rfile+        "GET"  -> processGET  spec req file ishtml rfile+        "HEAD" -> processHEAD spec req file ishtml rfile         _      -> return notAllowed     let hdr'= addServer hdr         (response, mlen) = case body of@@ -52,11 +52,11 @@                 in (responseLBS st hdr' bd, Just len)             BodyFile afile rng ->                 let (len, mfp) = case rng of-                        Entire bytes    -> (bytes, Nothing)+                        -- sendfile of Linux does not support the entire file+                        Entire bytes    -> (bytes, Just (FilePart 0 bytes))                         Part skip bytes -> (bytes, Just (FilePart skip bytes))                     hdr''  = addLength hdr' len-                    afile' = BS.unpack afile-                in (ResponseFile st hdr'' afile' mfp, Just len)+                in (ResponseFile st hdr'' afile mfp, Just len)     liftIO $ logger spec req st mlen     return response   where@@ -77,55 +77,60 @@  ---------------------------------------------------------------- -processGET :: Request -> ByteString -> Bool -> Maybe ByteString -> Rsp-processGET req file ishtml rfile = runAny [-    tryGet req file ishtml-  , tryRedirect req rfile+processGET :: AppSpec -> Request -> ByteString -> Bool -> Maybe ByteString -> Rsp+processGET spec req file ishtml rfile = runAny [+    tryGet spec req file ishtml+  , tryRedirect spec req rfile   , just notFound   ] -tryGet :: Request -> ByteString -> Bool -> MRsp-tryGet req file True  = runAnyMaybe $ map (tryGetFile req file True) langs+tryGet :: AppSpec -> Request -> ByteString -> Bool -> MRsp+tryGet spec req file True  = runAnyMaybe $ map (tryGetFile spec req file True) langs   where     langs = langSuffixes req-tryGet req file False = tryGetFile req file False Nothing+tryGet spec req file False = tryGetFile spec req file False Nothing -tryGetFile :: Request -> ByteString -> Bool -> Lang -> MRsp-tryGetFile req file ishtml mlang = do+tryGetFile :: AppSpec -> Request -> ByteString -> Bool -> Lang -> MRsp+tryGetFile spec req file ishtml mlang = do     let file' = maybe file (file +++) mlang-    liftIO (fileInfo file') |>| \(size, mtime) -> do-      let hdr = newHeader ishtml file mtime+    liftIO (getFileInfo spec file') |>| \finfo -> do+      let mtime = fileInfoTime finfo+          size = fileInfoSize finfo+          sfile = fileInfoName finfo+          hdr = newHeader ishtml file mtime           Just pst = ifmodified req size mtime -- never Nothing                  ||| ifunmodified req size mtime                  ||| ifrange req size mtime                  ||| unconditional req size mtime       case pst of           Full st-            | st == statusOK -> just $ RspSpec statusOK hdr (BodyFile file' (Entire size))+            | st == statusOK -> just $ RspSpec statusOK hdr (BodyFile sfile (Entire size))             | otherwise      -> just $ RspSpec st hdr NoBody -          Partial skip len   -> just $ RspSpec statusPartialContent hdr (BodyFile file' (Part skip len))+          Partial skip len   -> just $ RspSpec statusPartialContent hdr (BodyFile sfile (Part skip len))  ---------------------------------------------------------------- -processHEAD :: Request -> ByteString -> Bool -> Maybe ByteString -> Rsp-processHEAD req file ishtml rfile = runAny [-    tryHead req file ishtml-  , tryRedirect req rfile+processHEAD :: AppSpec -> Request -> ByteString -> Bool -> Maybe ByteString -> Rsp+processHEAD spec req file ishtml rfile = runAny [+    tryHead spec req file ishtml+  , tryRedirect spec req rfile   , just notFound   ] -tryHead :: Request -> ByteString -> Bool -> MRsp-tryHead req file True  = runAnyMaybe $ map (tryHeadFile req file True) langs+tryHead :: AppSpec -> Request -> ByteString -> Bool -> MRsp+tryHead spec req file True  = runAnyMaybe $ map (tryHeadFile spec req file True) langs   where     langs = langSuffixes req-tryHead req file False= tryHeadFile req file False Nothing+tryHead spec req file False= tryHeadFile spec req file False Nothing -tryHeadFile :: Request -> ByteString -> Bool -> Lang -> MRsp-tryHeadFile req file ishtml mlang = do+tryHeadFile :: AppSpec -> Request -> ByteString -> Bool -> Lang -> MRsp+tryHeadFile spec req file ishtml mlang = do     let file' = maybe file (file +++) mlang-    liftIO (fileInfo file') |>| \(size, mtime) -> do-      let hdr = newHeader ishtml file mtime+    liftIO (getFileInfo spec file') |>| \finfo -> do+      let mtime = fileInfoTime finfo+          size = fileInfoSize finfo+          hdr = newHeader ishtml file mtime           Just pst = ifmodified req size mtime -- never Nothing                  ||| Just (Full statusOK)       case pst of@@ -134,17 +139,17 @@  ---------------------------------------------------------------- -tryRedirect  :: Request -> Maybe ByteString -> MRsp-tryRedirect _   Nothing     = nothing-tryRedirect req (Just file) =-    runAnyMaybe $ map (tryRedirectFile req file) langs+tryRedirect  :: AppSpec -> Request -> Maybe ByteString -> MRsp+tryRedirect _ _ Nothing = nothing+tryRedirect spec req (Just file) =+    runAnyMaybe $ map (tryRedirectFile spec req file) langs   where     langs = langSuffixes req -tryRedirectFile :: Request -> ByteString -> Lang -> MRsp-tryRedirectFile req file mlang = do+tryRedirectFile :: AppSpec -> Request -> ByteString -> Lang -> MRsp+tryRedirectFile spec req file mlang = do     let file' = maybe file (file +++) mlang-    minfo <- liftIO $ fileInfo file'+    minfo <- liftIO $ getFileInfo spec file'     case minfo of       Nothing -> nothing       Just _  -> just $ RspSpec statusMovedPermanently hdr NoBody
Network/Wai/Application/Classic/FileInfo.hs view
@@ -1,9 +1,7 @@ module Network.Wai.Application.Classic.FileInfo where -import Control.Exception import Data.ByteString (ByteString) import qualified Data.ByteString as BS hiding (unpack)-import qualified Data.ByteString.Char8 as BS (unpack) import Network.HTTP.Date import Network.HTTP.Types import Network.Wai@@ -12,24 +10,6 @@ import Network.Wai.Application.Classic.Range import Network.Wai.Application.Classic.Types import Network.Wai.Application.Classic.Utils-import System.Posix.Files---------------------------------------------------------------------- This function is slow.--- So, let's avoid using doesFileExist which uses getFilesStatus.-fileInfo :: ByteString -> IO (Maybe (Integer, HTTPDate))-fileInfo file = handle nothing $ do-    fs <- getFileStatus (BS.unpack file)-    if doesExist fs-       then return $ Just (size fs, mtime fs)-       else return Nothing-  where-    nothing :: IOException -> IO (Maybe (Integer, HTTPDate))-    nothing _ = return Nothing-    size = fromIntegral . fileSize-    mtime = epochTimeToHTTPDate . modificationTime-    doesExist = not . isDirectory  ---------------------------------------------------------------- 
Network/Wai/Application/Classic/Types.hs view
@@ -2,6 +2,7 @@  import Data.ByteString (ByteString) import qualified Data.ByteString.Lazy as BL (ByteString)+import Network.HTTP.Date import Network.HTTP.Types import Network.Wai @@ -14,8 +15,15 @@   , isHTML :: ByteString -> Bool     -- | A function for logging. The third argument is a body size.   , logger :: Request -> Status -> Maybe Integer -> IO ()+  , getFileInfo :: ByteString -> IO (Maybe FileInfo)   } +data FileInfo = FileInfo {+    fileInfoName :: FilePath+  , fileInfoSize :: Integer+  , fileInfoTime :: HTTPDate+  }+ data FileRoute = FileRoute {     -- | Path prefix to be matched to 'pathInfo'.     fileSrc :: ByteString@@ -45,7 +53,7 @@     -- | Body as Lazy ByteString.   | BodyLBS BL.ByteString     -- | Body as a file.-  | BodyFile ByteString Range+  | BodyFile String Range  data Range =     -- | Entire file showing its file size
wai-app-file-cgi.cabal view
@@ -1,5 +1,5 @@ Name:                   wai-app-file-cgi-Version:                0.2.2+Version:                0.2.3 Author:                 Kazu Yamamoto <kazu@iij.ad.jp> Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp> License:                BSD3