@@ -19,11 +19,7 @@
20---------------------------------------------------------
20---------------------------------------------------------
22−-- | A fast, light-weight HTTP server handler for WAI. Some random notes (a FAQ, if you will):
22+-- | A fast, light-weight HTTP server handler for WAI.
24−-- * When a 'ResponseFile' indicates a file which does not exist, an exception
25−-- is thrown. This will close the connection to the client as well. You should
26−-- handle file existance checks at the application level.
27module Network.Wai.Handler.Warp
23module Network.Wai.Handler.Warp
28 ( -- * Run a Warp server
24 ( -- * Run a Warp server
@@ -85,6 +81,7 @@ import Control.Exception
85 , fromException, AsyncException (ThreadKilled)
81 , fromException, AsyncException (ThreadKilled)
86 , bracketOnError
82 , bracketOnError
87 , IOException
83 , IOException
89import Control.Concurrent (forkIO)
86import Control.Concurrent (forkIO)
90import Data.Maybe (fromMaybe, isJust)
87import Data.Maybe (fromMaybe, isJust)
@@ -513,27 +510,33 @@ sendResponse th req conn r = sendResponse' r
513 sendHeader = connSendMany conn . L.toChunks . toLazyByteString
510 sendHeader = connSendMany conn . L.toChunks . toLazyByteString
515 sendResponse' :: Response -> ResourceT IO Bool
512 sendResponse' :: Response -> ResourceT IO Bool
516− sendResponse' (ResponseFile s hs fp mpart) = liftIO $ do
513+ sendResponse' (ResponseFile s hs fp mpart) = do
517− (lengthyHeaders, cl) <-
514+ eres <-
518 case (LI.readDecimal_ `fmap` lookup "content-length" hs, mpart) of
515 case (LI.readDecimal_ `fmap` lookup "content-length" hs, mpart) of
519− (Just cl, _) -> return (hs, cl)
516+ (Just cl, _) -> return $ Right (hs, cl)
520− (Nothing, Nothing) -> do
517+ (Nothing, Nothing) -> liftIO $ try $ do
521 cl <- P.fileSize `fmap` P.getFileStatus fp
518 cl <- P.fileSize `fmap` P.getFileStatus fp
522 return $ addClToHeaders cl
519 return $ addClToHeaders cl
523 (Nothing, Just part) -> do
520 (Nothing, Just part) -> do
524 let cl = filePartByteCount part
521 let cl = filePartByteCount part
525− return $ addClToHeaders cl
522+ return $ Right $ addClToHeaders cl
524+ Left (e :: SomeException) -> sendResponse' $ responseLBS
526+ [("Content-Type", "text/plain")]
528+ Right (lengthyHeaders, cl) -> liftIO $ do
526− let headers' = headers version s lengthyHeaders
529+ let headers' = headers version s lengthyHeaders
527− sendHeader $ headers' False
530+ sendHeader $ headers' False
528− T.tickle th
531+ T.tickle th
529− if hasBody s req then do
532+ if hasBody s req then do
530− case mpart of
533+ case mpart of
531− Nothing -> connSendFile conn fp 0 cl (T.tickle th)
534+ Nothing -> connSendFile conn fp 0 cl (T.tickle th)
532− Just part -> connSendFile conn fp (filePartOffset part) (filePartByteCount part) (T.tickle th)
535+ Just part -> connSendFile conn fp (filePartOffset part) (filePartByteCount part) (T.tickle th)
533− T.tickle th
536+ T.tickle th
534− return isPersist
537+ return isPersist
536− return isPersist
539+ return isPersist
538 addClToHeaders cl = (("Content-Length", B.pack $ show cl):hs, fromIntegral cl)
541 addClToHeaders cl = (("Content-Length", B.pack $ show cl):hs, fromIntegral cl)