Commit f38c3c9b authored by Antoine Fontaine's avatar Antoine Fontaine 🎱
Browse files

Improve error handling

parent 41db738d
......@@ -2,7 +2,6 @@
* Autodetect mimetype if field is empty.
* Good practices testing.
* Improve error reporting (send 404&stuff).
* Fast continuous-integration.
* Import script for previous pastes.
* Add ETags for caching.
......
......@@ -25,8 +25,8 @@ import Protolude
import Paste.API
import Paste.Database
import Paste.Homepage
import Paste.Utils
import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Time.Calendar
import Data.Time.Clock
......@@ -52,10 +52,11 @@ servePastes :: ConnectionPool -- ^ Database pool.
-> Text -- ^ Hash of the requested paste
-> Handler (Headers '[Header "Content-Type" Text] ByteString)
servePastes pool pasteDir hash = do
mimetype <- liftIO $ do Just mimetype <- lookupFiletype pool hash
return mimetype
response <- liftIO $ B.readFile (pasteDir ++ T.unpack hash)
return $ addHeader mimetype response
mimetype <- liftIO $ lookupFiletype pool hash
response <- liftIO $ readFileMaybe (pasteDir ++ T.unpack hash)
case (mimetype, response) of
(Just mimetype, Just response) -> return $ addHeader mimetype response
_ -> throwError err404 { errBody = "This paste doesn't exist. Maybe it expired?\n" }
-- | Process a file upload request to our server.
processUpload :: ConnectionPool -- ^ Database pool.
......@@ -68,14 +69,9 @@ processUpload :: ConnectionPool -- ^ Database pool.
processUpload pool pasteDir instanceUrl reqAddr mXForward multipData =
-- Process and check request: first and foremost, do we have a file ?
case head $ files multipData of
Nothing -> throwError err400 { errBody = "You must include a file in the multipart/formdata you upload!" }
Nothing -> throwError err400 { errBody = "You must include a file in the multipart/formdata you upload!\n" }
Just upload -> do
--size <- liftIO $ getFileSize (fdPayload upload)
---- Ensure file isn't too big
--when (size > 1*1024*1024) $
-- throwError err413 { errBody = "Request size exceeded 1MiB." }
-- Get information to store.
now <- liftIO getCurrentTime
......@@ -135,7 +131,7 @@ parseTimeDiff now input = do
let reg = mkRegex "^([0-9]+)([shdwm])?$"
seconds <- case matchRegex reg (T.unpack input) of
Just (i:u:_) -> return $ (read i) * (parseUnit u)
_ -> throwError err400 { errBody = "Invalid expiration date specified" }
_ -> throwError err400 { errBody = "Invalid expiration date specified\n" }
return $ addUTCTime (fromIntegral seconds) now
-- | Return the number of seconds contained in the given unit.
......
......@@ -14,8 +14,10 @@ module Paste.Utils where
import Protolude
import Data.List
import System.Random
import qualified Data.ByteString as B
import Data.List
import System.IO.Error
import System.Random
-- | List of available characters for creating the hash.
pasteChars :: [Char]
......@@ -25,3 +27,12 @@ pasteChars = ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9']
pickElem :: [a] -- ^ The list to pick from.
-> IO a
pickElem xs = (xs !!) <$> randomRIO (0, length xs - 1)
-- | Read the file if it exists, else return Nothing.
-- Useful for reading golden files.
-- Taken from https://hackage.haskell.org/package/tasty-silver-3.2.1/docs/src/Test.Tasty.Silver.Internal.html#readFileMaybe
readFileMaybe :: FilePath -> IO (Maybe B.ByteString)
readFileMaybe path = catchJust
(\e -> if isDoesNotExistErrorType (ioeGetErrorType e) then Just () else Nothing)
(Just <$> B.readFile path)
(const $ return Nothing)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment