module Ketchup.Utils
( breakBS
, fallback
, parseBody
, sendBadRequest
, sendNotFound
, sendReply
, statusMsg
, subBS
, trim
) where
import qualified Data.ByteString.Char8 as B
import Data.Char (isSpace)
import qualified Data.List as List
import Network
import Network.Socket.ByteString
statusMsg :: Int
-> B.ByteString
statusMsg 200 = "200 OK"
statusMsg 201 = "201 Created"
statusMsg 204 = "204 No Content"
statusMsg 400 = "400 Bad Request"
statusMsg 401 = "401 Unauthorized"
statusMsg 402 = "402 Payment Required"
statusMsg 403 = "403 Forbidden"
statusMsg 404 = "404 Not Found"
statusMsg 405 = "405 Method Not Allowed"
statusMsg 410 = "410 Gone"
statusMsg 500 = "500 Internal Server Error"
statusMsg 501 = "501 Not Implemented"
statusMsg 502 = "502 Bad Gateway"
statusMsg 503 = "503 Service Unavailable"
statusMsg _ = "500 Internal Server Error"
sendBadRequest :: Socket -> IO ()
sendBadRequest client =
sendReply client 400 [("Content-Type",["text/plain"])] "400 Bad Request\n"
sendNotFound :: Socket -> IO ()
sendNotFound client =
sendReply client 404 [("Content-Type",["text/plain"])] "404 Not Found\n"
sendReply :: Socket
-> Int
-> [(B.ByteString, [B.ByteString])]
-> B.ByteString
-> IO ()
sendReply client status headers body =
sendAll client reply
where
reply = B.concat [ "HTTP/1.1 ", statusMsg status,"\r\n"
, "Content-Length: ", B.pack $ show $ B.length body, "\r\n"
, "Connection: close\r\n", heads, "\r\n", body]
heads = B.concat $ map toHeader headers
toHeader x = B.concat [ fst x, ": "
, B.concat $ List.intersperse "," $ snd x
, "\r\n"]
trim :: B.ByteString -> B.ByteString
trim = f . f where f = B.reverse . B.dropWhile isSpace
breakBS :: B.ByteString -> B.ByteString -> (B.ByteString, B.ByteString)
breakBS delimiter source =
(first, second)
where
first = fst broke
second = B.drop (B.length delimiter) $ snd broke
broke = B.breakSubstring delimiter source
subBS :: Int -> Int -> B.ByteString -> B.ByteString
subBS start len = B.take len . B.drop start
parseBody :: B.ByteString -> [(B.ByteString, B.ByteString)]
parseBody body = map (breakBS "=") $ B.split '&' body
fallback :: Maybe a -> a -> a
fallback (Just x) _ = x
fallback Nothing def = def