-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttparse.hs
50 lines (39 loc) · 1.4 KB
/
httparse.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as B8
import Data.Attoparsec as P
import Data.Attoparsec.Char8 (char8, endOfLine)
import qualified Data.Attoparsec.Char8 as P8
import Control.Applicative hiding (many)
import Data.Word (Word8)
import Data.Char
data Request = Request {
requestMethod :: ByteString
, requestUri :: ByteString
, requestVersion :: ByteString
} deriving (Eq, Ord, Show)
requestLine :: Parser Request
requestLine = do
method <- P.takeWhile1 isToken <* char8 ' '
cheesyUri <- P8.takeWhile1 (/=' ') <* char8 ' '
ver <- version <* endOfLine
return (Request method cheesyUri ver)
version :: Parser ByteString
version = string "HTTP/" >>
P8.takeWhile (\c -> isDigit c || c == '.')
betterVersion :: Parser (Int, Int)
betterVersion = string "HTTP/" *>
((,) <$> (P8.decimal <* char8 '.') <*> P8.decimal)
-- The first line of an HTTP response
-- Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
-- To test in ghci:
-- :set -XOverloadedStrings
-- P.parseOnly responseLine "HTTP/1.1 200 OK\r\n"
responseLine :: Parser ((Int,Int,Int), ByteString)
responseLine =
(,) <$> (betterVersion *> sp *> xxx <* sp)
<*> P.takeTill P8.isEndOfLine <* P8.endOfLine
where xxx = (,,) <$> x <*> x <*> x
x = digitToInt <$> P8.digit
sp = char8 ' '
isToken = undefined