X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=Lucu.git;a=blobdiff_plain;f=Network%2FHTTP%2FLucu%2FPostprocess.hs;h=6e8a5e6753b5bafdf6bbebc2448b76730e07afd3;hp=062a3bf6203c303195684999a4198cb510338700;hb=15aa04a569fb13fb0793389f78f52b0255083cef;hpb=ea8f823ffa1004582d403c69f52a83e20486269f diff --git a/Network/HTTP/Lucu/Postprocess.hs b/Network/HTTP/Lucu/Postprocess.hs index 062a3bf..6e8a5e6 100644 --- a/Network/HTTP/Lucu/Postprocess.hs +++ b/Network/HTTP/Lucu/Postprocess.hs @@ -6,7 +6,9 @@ module Network.HTTP.Lucu.Postprocess import Control.Concurrent.STM import Control.Monad -import Data.Char +import Data.ByteString.Base (ByteString) +import qualified Data.ByteString.Char8 as C8 +import Data.IORef import Data.Maybe import GHC.Conc (unsafeIOToSTM) import Network.HTTP.Lucu.Abortion @@ -18,6 +20,7 @@ import Network.HTTP.Lucu.RFC1123DateTime import Network.HTTP.Lucu.Request import Network.HTTP.Lucu.Response import System.Time +import System.IO.Unsafe {- @@ -64,11 +67,11 @@ postprocess itr $ Just ("The status code is not good for a final status: " ++ show sc) - when (sc == MethodNotAllowed && getHeader "Allow" res == Nothing) + when (sc == MethodNotAllowed && getHeader (C8.pack "Allow") res == Nothing) $ abortSTM InternalServerError [] $ Just ("The status was " ++ show sc ++ " but no Allow header.") - when (sc /= NotModified && isRedirection sc && getHeader "Location" res == Nothing) + when (sc /= NotModified && isRedirection sc && getHeader (C8.pack "Location") res == Nothing) $ abortSTM InternalServerError [] $ Just ("The status code was " ++ show sc ++ " but no Location header.") @@ -97,37 +100,40 @@ postprocess itr status == ResetContent || status == NotModified ) - updateRes itr $! deleteHeader "Content-Length" - updateRes itr $! deleteHeader "Transfer-Encoding" + updateRes itr $! deleteHeader (C8.pack "Content-Length") + updateRes itr $! deleteHeader (C8.pack "Transfer-Encoding") - cType <- readHeader itr "Content-Type" + cType <- readHeader itr (C8.pack "Content-Type") when (cType == Nothing) - $ updateRes itr $ setHeader "Content-Type" defaultPageContentType + $ updateRes itr $ setHeader (C8.pack "Content-Type") defaultPageContentType if canHaveBody then when (reqVer == HttpVersion 1 1) - $ do updateRes itr $! setHeader "Transfer-Encoding" "chunked" + $ do updateRes itr $! setHeader (C8.pack "Transfer-Encoding") (C8.pack "chunked") writeItr itr itrWillChunkBody True else -- body 関連のヘッダを削除。但し HEAD なら Content-* は殘す when (reqMethod req /= HEAD) - $ do updateRes itr $! deleteHeader "Content-Type" - updateRes itr $! deleteHeader "Etag" - updateRes itr $! deleteHeader "Last-Modified" - - conn <- readHeader itr "Connection" - case fmap (map toLower) conn of - Just "close" -> writeItr itr itrWillClose True - _ -> return () + $ do updateRes itr $! deleteHeader (C8.pack "Content-Type") + updateRes itr $! deleteHeader (C8.pack "Etag") + updateRes itr $! deleteHeader (C8.pack "Last-Modified") + + conn <- readHeader itr (C8.pack "Connection") + case conn of + Nothing -> return () + Just value -> if value `noCaseEq` C8.pack "close" then + writeItr itr itrWillClose True + else + return () willClose <- readItr itr itrWillClose id when willClose - $ updateRes itr $! setHeader "Connection" "close" + $ updateRes itr $! setHeader (C8.pack "Connection") (C8.pack "close") when (reqMethod req == HEAD || not canHaveBody) $ writeTVar (itrWillDiscardBody itr) True - readHeader :: Interaction -> String -> STM (Maybe String) + readHeader :: Interaction -> ByteString -> STM (Maybe ByteString) readHeader itr name = itr `seq` name `seq` readItr itr itrResponse $ getHeader name @@ -144,12 +150,29 @@ completeUnconditionalHeaders conf res return res >>= compServer >>= compDate >>= return where compServer res - = case getHeader "Server" res of - Nothing -> return $ addHeader "Server" (cnfServerSoftware conf) res + = case getHeader (C8.pack "Server") res of + Nothing -> return $ setHeader (C8.pack "Server") (cnfServerSoftware conf) res Just _ -> return res compDate res - = case getHeader "Date" res of - Nothing -> do time <- getClockTime - return $ addHeader "Date" (formatHTTPDateTime time) res - Just _ -> return res \ No newline at end of file + = case getHeader (C8.pack "Date") res of + Nothing -> do date <- getCurrentDate + return $ setHeader (C8.pack "Date") date res + Just _ -> return res + + +cache :: IORef (ClockTime, ByteString) +cache = unsafePerformIO $ + newIORef (TOD 0 0, undefined) +{-# NOINLINE cache #-} + +getCurrentDate :: IO ByteString +getCurrentDate = do now@(TOD curSec _) <- getClockTime + (TOD cachedSec _, cachedStr) <- readIORef cache + + if curSec == cachedSec then + return cachedStr + else + do let dateStr = C8.pack $ formatHTTPDateTime now + writeIORef cache (now, dateStr) + return dateStr \ No newline at end of file