X-Git-Url: http://andersk.mit.edu/gitweb/scripts-static-cat.git/blobdiff_plain/59962b4ac6b131aec2940ccfa1fa0735f7a0445d..cee07ba63331e8b3dd39756a38fe4b913dfaffe0:/StaticCat.hs diff --git a/StaticCat.hs b/StaticCat.hs index f7e4ad8..be7fbe0 100644 --- a/StaticCat.hs +++ b/StaticCat.hs @@ -108,38 +108,46 @@ checkRange mTime size = do Just (a, b) | a <= b -> return $ Just (a, b) _ -> throwExceptionCGI BadRange +outputAll :: Handle -> FileOffset -> CGI CGIResult +outputAll h size = do + setHeader "Content-Length" $ show size + outputFPS =<< liftIO (B.hGetContents h) + +outputRange :: Handle -> FileOffset -> Maybe (FileOffset, FileOffset) -> CGI CGIResult +outputRange h size Nothing = outputAll h size +outputRange h size (Just (a, b)) = do + let len = b - a + 1 + + setStatus 206 "Partial Content" + setHeader "Content-Range" $ + "bytes " ++ show a ++ "-" ++ show b ++ "/" ++ show size + setHeader "Content-Length" $ show len + liftIO $ hSeek h AbsoluteSeek (fromIntegral a) + outputFPS =<< liftIO (B.hGet h (fromIntegral len)) + serveFile :: FilePath -> CGI CGIResult serveFile file = (`catchExceptionCGI` outputMyError) $ do checkExtension file checkMethod $ do - h <- (`catchExceptionCGI` \e -> - if isDoesNotExistError e then throwExceptionCGI NotFound - else if isPermissionError e then throwExceptionCGI Forbidden - else throwExceptionCGI e) $ - liftIO $ openBinaryFile file ReadMode - (`catchCGI` \e -> - (liftIO $ hClose h) >> throwCGI e) $ do + let handleOpenError e = + if isDoesNotExistError e then throwExceptionCGI NotFound + else if isPermissionError e then throwExceptionCGI Forbidden + else throwExceptionCGI e + h <- liftIO (openBinaryFile file ReadMode) `catchExceptionCGI` handleOpenError + let handlePostOpenError e = do + liftIO $ hClose h + throwCGI e + (`catchCGI` handlePostOpenError) $ do status <- liftIO $ hGetStatus h let mTime = modificationTime status size = fileSize status checkModified mTime - checkRange mTime size >>= maybe - (do - setHeader "Content-Length" $ show size - outputFPS =<< (liftIO $ B.hGetContents h)) - (\(a, b) -> do - let len = b - a + 1 - - setStatus 206 "Partial Content" - setHeader "Content-Range" $ - "bytes " ++ show a ++ "-" ++ show b ++ "/" ++ show size - setHeader "Content-Length" $ show len - liftIO $ hSeek h AbsoluteSeek (fromIntegral a) - outputFPS =<< (liftIO $ B.hGet h (fromIntegral len))) + range <- checkRange mTime size + outputRange h size range main :: IO () main = runCGI $ handleErrors $ serveFile =<< pathTranslated