]> gitweb @ CieloNegro.org - Lucu.git/blobdiff - Network/HTTP/Lucu/Preprocess.hs
Fixed build failure on recent GHC and other libraries
[Lucu.git] / Network / HTTP / Lucu / Preprocess.hs
index 5e1d095151fb16b9a59e86730af5946971317638..9f9fa0d68c3b83f187c6316213cc100f39cdc5cf 100644 (file)
@@ -1,4 +1,6 @@
--- #hide
+{-# LANGUAGE
+    BangPatterns
+  #-}
 module Network.HTTP.Lucu.Preprocess
     ( preprocess
     )
@@ -6,6 +8,8 @@ module Network.HTTP.Lucu.Preprocess
 
 import           Control.Concurrent.STM
 import           Control.Monad
+import qualified Data.ByteString as Strict (ByteString)
+import qualified Data.ByteString.Char8 as C8 hiding (ByteString)
 import           Data.Char
 import           Data.Maybe
 import           Network.HTTP.Lucu.Config
@@ -14,8 +18,6 @@ import           Network.HTTP.Lucu.HttpVersion
 import           Network.HTTP.Lucu.Interaction
 import           Network.HTTP.Lucu.Request
 import           Network.HTTP.Lucu.Response
-import           Network.HTTP.Lucu.Utils
-import           Network
 import           Network.URI
 
 {-
@@ -47,12 +49,9 @@ import           Network.URI
 
 -}
 
-import GHC.Conc (unsafeIOToSTM)
-
 preprocess :: Interaction -> STM ()
-preprocess itr
-    = itr `seq`
-      do req <- readItr itr itrRequest fromJust
+preprocess !itr
+    = do req <- readItr itr itrRequest fromJust
 
          let reqVer = reqVersion req
 
@@ -71,100 +70,88 @@ preprocess itr
                 completeAuthority req
 
                 case reqMethod req of
-                  GET  -> return ()
-                  HEAD -> writeItr itr itrWillDiscardBody True
-                  POST -> writeItr itr itrRequestHasBody True
-                  PUT  -> writeItr itr itrRequestHasBody True
-                  _    -> setStatus NotImplemented
+                  GET    -> return ()
+                  HEAD   -> writeItr itr itrWillDiscardBody True
+                  POST   -> writeItr itr itrRequestHasBody True
+                  PUT    -> writeItr itr itrRequestHasBody True
+                  DELETE -> return ()
+                  _      -> setStatus NotImplemented
                   
-                mapM_ (preprocessHeader itr) (reqHeaders req)
+                preprocessHeader req
     where
       setStatus :: StatusCode -> STM ()
-      setStatus status
-          = status `seq`
-            updateItr itr itrResponse
+      setStatus !status
+          = updateItr itr itrResponse
             $! \ res -> res {
                           resStatus = status
                         }
 
       completeAuthority :: Request -> STM ()
-      completeAuthority req
-          = req `seq`
-            when (uriAuthority (reqURI req) == Nothing)
+      completeAuthority !req
+          = when (uriAuthority (reqURI req) == Nothing)
             $ if reqVersion req == HttpVersion 1 0 then
                   -- HTTP/1.0 なので Config から補完
                   do let conf = itrConfig itr
                          host = cnfServerHost conf
-                         port = case cnfServerPort conf of
-                                  PortNumber n -> Just $ fromIntegral n
-                                  _            -> Nothing
+                         port = itrLocalPort itr
                          portStr
                               = case port of
-                                  Just 80 -> Just ""
-                                  Just n  -> Just $ ":" ++ show n
-                                  Nothing -> Nothing
-                     case portStr of
-                       Just str -> updateAuthority host str
-                       -- FIXME: このエラーの原因は、listen してゐるソ
-                       -- ケットが INET でない故にポート番號が分からな
-                       -- い事だが、その事をどうにかして通知した方が良
-                       -- いと思ふ。stderr?
-                       Nothing  -> setStatus InternalServerError
+                                  80 -> ""
+                                  n  -> ':' : show n
+                     updateAuthority host (C8.pack portStr)
               else
-                  do case getHeader "Host" req of
-                       Just str -> let (host, portStr) = parseHost str
-                                   in updateAuthority host portStr
-                       Nothing  -> setStatus BadRequest
+                  case getHeader (C8.pack "Host") req of
+                    Just str -> let (host, portStr) = parseHost str
+                                in updateAuthority host portStr
+                    Nothing  -> setStatus BadRequest
 
 
-      parseHost :: String -> (String, String)
-      parseHost = break (== ':')
+      parseHost :: Strict.ByteString -> (Strict.ByteString, Strict.ByteString)
+      parseHost = C8.break (== ':')
 
 
-      updateAuthority :: String -> String -> STM ()
-      updateAuthority host portStr
-          = host `seq` portStr `seq`
-            updateItr itr itrRequest
+      updateAuthority :: Strict.ByteString -> Strict.ByteString -> STM ()
+      updateAuthority !host !portStr
+          = updateItr itr itrRequest
             $! \ (Just req) -> Just req {
                                  reqURI = let uri = reqURI req
                                           in uri {
                                                uriAuthority = Just URIAuth {
                                                                    uriUserInfo = ""
-                                                                 , uriRegName  = host
-                                                                 , uriPort     = portStr
+                                                                 , uriRegName  = C8.unpack host
+                                                                 , uriPort     = C8.unpack portStr
                                                               }
                                              }
                                }
                 
 
-      preprocessHeader :: Interaction -> (String, String) -> STM ()
-      preprocessHeader itr (name, value)
-          = itr `seq` name `seq` value `seq`
-            case map toLower name of
-
-              "expect"
-                  -> if value `noCaseEq'` "100-continue" then
-                         writeItr itr itrExpectedContinue True
-                     else
-                         setStatus ExpectationFailed
-
-              "transfer-encoding"
-                  -> case map toLower value of
-                       "identity" -> return ()
-                       "chunked"  -> writeItr itr itrRequestIsChunked True
-                       _          -> setStatus NotImplemented
-
-              "content-length"
-                  -> if all isDigit value then
-                         do let len = read value
-                            writeItr itr itrReqChunkLength    $ Just len
-                            writeItr itr itrReqChunkRemaining $ Just len
-                     else
-                         setStatus BadRequest
-
-              "connection"
-                  -> case map toLower value of
-                       "close"      -> writeItr itr itrWillClose True
-                       _            -> return ()
-
-              _ -> return ()
\ No newline at end of file
+      preprocessHeader :: Request -> STM ()
+      preprocessHeader !req
+          = do case getHeader (C8.pack "Expect") req of
+                 Nothing    -> return ()
+                 Just value -> if value `noCaseEq` C8.pack "100-continue" then
+                                   writeItr itr itrExpectedContinue True
+                               else
+                                   setStatus ExpectationFailed
+
+               case getHeader (C8.pack "Transfer-Encoding") req of
+                 Nothing    -> return ()
+                 Just value -> unless (value `noCaseEq` C8.pack "identity")
+                                   $ if value `noCaseEq` C8.pack "chunked" then
+                                         writeItr itr itrRequestIsChunked True
+                                     else
+                                         setStatus NotImplemented
+
+               case getHeader (C8.pack "Content-Length") req of
+                 Nothing    -> return ()
+                 Just value -> if C8.all isDigit value then
+                                   do let Just (len, _) = C8.readInt value
+                                      writeItr itr itrReqChunkLength    $ Just len
+                                      writeItr itr itrReqChunkRemaining $ Just len
+                               else
+                                   setStatus BadRequest
+
+               case getHeader (C8.pack "Connection") req of
+                 Nothing    -> return ()
+                 Just value -> when (value `noCaseEq` C8.pack "close")
+                                   $ writeItr itr itrWillClose True