import Data.Maybe
import qualified Data.Sequence as S
import Data.Sequence ((<|))
+import GHC.Conc (unsafeIOToSTM)
import Network.Socket
import Network.HTTP.Lucu.Config
import Network.HTTP.Lucu.Chunk
import System.IO
-requestReader :: Config -> ResTree -> Handle -> SockAddr -> InteractionQueue -> IO ()
-requestReader cnf tree h addr tQueue
- = cnf `seq` tree `seq` h `seq` addr `seq` tQueue `seq`
+requestReader :: Config -> ResTree -> [FallbackHandler] -> Handle -> SockAddr -> InteractionQueue -> IO ()
+requestReader cnf tree fbs h addr tQueue
+ = cnf `seq` tree `seq` fbs `seq` h `seq` addr `seq` tQueue `seq`
do catch (do input <- B.hGetContents h
acceptRequest input) $ \ exc ->
case exc of
-- Request 應答を設定し、それを出力してから切斷するやう
-- に ResponseWriter に通知する。
case parse requestP input of
- (Success req , input') -> acceptParsableRequest req input'
- (IllegalInput, _ ) -> acceptNonparsableRequest BadRequest
- (ReachedEOF , _ ) -> acceptNonparsableRequest BadRequest
+ (# Success req , input' #) -> acceptParsableRequest req input'
+ (# IllegalInput, _ #) -> acceptNonparsableRequest BadRequest
+ (# ReachedEOF , _ #) -> acceptNonparsableRequest BadRequest
acceptNonparsableRequest :: StatusCode -> IO ()
acceptNonparsableRequest status
if isErr then
acceptSemanticallyInvalidRequest itr input
else
- case findResource tree $ reqURI req of
- Nothing -- Resource が無かった
- -> acceptRequestForNonexistentResource itr input
+ do rsrcM <- unsafeIOToSTM $ findResource tree fbs $ reqURI req
+ case rsrcM of
+ Nothing -- Resource が無かった
+ -> acceptRequestForNonexistentResource itr input
- Just (rsrcPath, rsrcDef) -- あった
- -> acceptRequestForExistentResource itr input rsrcPath rsrcDef
+ Just (rsrcPath, rsrcDef) -- あった
+ -> acceptRequestForExistentResource itr input rsrcPath rsrcDef
action
acceptSemanticallyInvalidRequest :: Interaction -> ByteString -> STM (IO ())
-- 讀み終へてゐない
do let (_, input') = B.splitAt (fromIntegral
$ fromJust remainingM) input
- (footerR, input'') = parse chunkFooterP input'
+ (# footerR, input'' #) = parse chunkFooterP input'
if footerR == Success () then
-- チャンクフッタを正常に讀めた
if newRemaining == Just 0 then
-- チャンクフッタを讀む
case parse chunkFooterP input' of
- (Success _, input'')
+ (# Success _, input'' #)
-> do updateStates
return $ observeChunkedRequest itr input''
- _ -> return $ chunkWasMalformed itr
+ (# _, _ #)
+ -> return $ chunkWasMalformed itr
else
-- まだチャンクの終はりに達してゐない
do updateStates
= {-# SCC "seekNextChunk" #-}
case parse chunkHeaderP input of
-- 最終チャンク (中身が空)
- (Success 0, input')
+ (# Success 0, input' #)
-> case parse chunkTrailerP input' of
- (Success _, input'')
+ (# Success _, input'' #)
-> do writeItr itr itrReqChunkLength $ Nothing
writeItr itr itrReqChunkRemaining $ Nothing
writeItr itr itrReqChunkIsOver True
return $ acceptRequest input''
- _ -> return $ chunkWasMalformed itr
+ (# _, _ #)
+ -> return $ chunkWasMalformed itr
-- 最終でないチャンク
- (Success len, input')
+ (# Success len, input' #)
-> do writeItr itr itrReqChunkLength $ Just len
writeItr itr itrReqChunkRemaining $ Just len
return $ observeChunkedRequest itr input'
-- チャンクヘッダがをかしい
- _ -> return $ chunkWasMalformed itr
+ (# _, _ #)
+ -> return $ chunkWasMalformed itr
chunkWasMalformed :: Interaction -> IO ()
chunkWasMalformed itr