]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Request.hs
Fixed many bugs...
[Lucu.git] / Network / HTTP / Lucu / Request.hs
index 3fc0164ca167de1116504478e0363e6e421de1cb..66511e24c1f869490469ea637e0ea763ffd1ec34 100644 (file)
@@ -1,20 +1,28 @@
--- #prune
-
+{-# LANGUAGE
+    OverloadedStrings
+  , UnicodeSyntax
+  , ViewPatterns
+  #-}
 -- |Definition of things related on HTTP request.
 --
 -- In general you don't have to use this module directly.
 module Network.HTTP.Lucu.Request
     ( Method(..)
     , Request(..)
+    , reqMustHaveBody
     , requestP
     )
     where
-
-import           Network.HTTP.Lucu.Headers
-import           Network.HTTP.Lucu.HttpVersion
-import           Network.HTTP.Lucu.Parser
-import           Network.HTTP.Lucu.Parser.Http
-import           Network.URI
+import Control.Applicative
+import Control.Monad.Unicode
+import Data.Ascii (Ascii)
+import Data.Attoparsec.Char8
+import qualified Data.ByteString.Char8 as C8
+import Network.HTTP.Lucu.Headers
+import Network.HTTP.Lucu.HttpVersion
+import Network.HTTP.Lucu.Parser.Http
+import Network.URI
+import Prelude.Unicode
 
 -- |This is the definition of HTTP request methods, which shouldn't
 -- require any description.
@@ -26,28 +34,37 @@ data Method = OPTIONS
             | DELETE
             | TRACE
             | CONNECT
-            | ExtensionMethod !String
+            | ExtensionMethod !Ascii
               deriving (Eq, Show)
 
 -- |This is the definition of HTTP reqest.
 data Request
     = Request {
-        reqMethod  :: !Method
-      , reqURI     :: !URI
-      , reqVersion :: !HttpVersion
-      , reqHeaders :: !Headers
+        reqMethod   !Method
+      , reqURI      !URI
+      , reqVersion  !HttpVersion
+      , reqHeaders  !Headers
       }
-    deriving (Show, Eq)
+    deriving (Eq, Show)
 
 instance HasHeaders Request where
+    {-# INLINE getHeaders #-}
     getHeaders = reqHeaders
+    {-# INLINE setHeaders #-}
     setHeaders req hdr = req { reqHeaders = hdr }
 
+-- |Returns 'True' iff the 'Request' must have an entity body.
+reqMustHaveBody ∷ Request → Bool
+{-# INLINEABLE reqMustHaveBody #-}
+reqMustHaveBody (reqMethod → m)
+    | m ≡ POST  = True
+    | m ≡ PUT   = True
+    | otherwise = False
 
-requestP :: Parser Request
-requestP = do many crlf
-              (method, uri, version) <- requestLineP
-              headers                <- headersP
+requestP  Parser Request
+requestP = do skipMany crlf
+              (method, uri, version)  requestLineP
+              headers                 headersP
               return Request {
                            reqMethod  = method
                          , reqURI     = uri
@@ -55,35 +72,31 @@ requestP = do many crlf
                          , reqHeaders = headers
                          }
 
-
-requestLineP :: Parser (Method, URI, HttpVersion)
-requestLineP = do method <- methodP
+requestLineP ∷ Parser (Method, URI, HttpVersion)
+requestLineP = do method ← methodP
                   sp
-                  uri    <- uriP
+                  uri     uriP
                   sp
-                  ver    <- httpVersionP
+                  ver     httpVersionP
                   crlf
                   return (method, uri, ver)
 
+methodP ∷ Parser Method
+methodP = choice
+          [ string "OPTIONS" ≫ return OPTIONS
+          , string "GET"     ≫ return GET
+          , string "HEAD"    ≫ return HEAD
+          , string "POST"    ≫ return POST
+          , string "PUT"     ≫ return PUT
+          , string "DELETE"  ≫ return DELETE
+          , string "TRACE"   ≫ return TRACE
+          , string "CONNECT" ≫ return CONNECT
+          , ExtensionMethod <$> token
+          ]
 
-methodP :: Parser Method
-methodP = (let methods = [ ("OPTIONS", OPTIONS)
-                         , ("GET"    , GET    )
-                         , ("HEAD"   , HEAD   )
-                         , ("POST"   , POST   )
-                         , ("PUT"    , PUT    )
-                         , ("DELETE" , DELETE )
-                         , ("TRACE"  , TRACE  )
-                         , ("CONNECT", CONNECT)
-                         ]
-           in foldl (<|>) failP $ map (\ (str, mth)
-                                           -> string str >> return mth) methods)
-          <|>
-          token >>= return . ExtensionMethod
-
-
-uriP :: Parser URI
-uriP = do str <- many1 $ satisfy (\ c -> not (isCtl c || c == ' '))
+uriP ∷ Parser URI
+uriP = do bs ← takeWhile1 (\c → (¬) (isCtl c ∨ c ≡ '\x20'))
+          let str = C8.unpack bs
           case parseURIReference str of
-            Nothing  -> failP
-            Just uri -> return uri
\ No newline at end of file
+            Nothing  -> fail ("Unparsable URI: " ⧺ str)
+            Just uri -> return uri