merge GET and POST params in debug logger

This commit is contained in:
Greg Weber 2011-07-15 09:40:47 -07:00
parent 29076d018b
commit a9df06e5eb
3 changed files with 40 additions and 13 deletions

View File

@ -4,9 +4,11 @@ module Network.Wai.Middleware.Debug
, debugDest
) where
import Network.Wai (Middleware, requestMethod, requestHeaders, rawPathInfo, rawQueryString)
import Network.Wai.Parse (parseRequestBody, lbsSink, fileName)
import Network.Wai (Request(..), Middleware)
import Network.Wai.Parse (parseRequestBody, lbsSink, fileName, Param, File)
import Data.ByteString.Char8 (unpack)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import System.IO (hPutStrLn, stderr)
import Control.Monad.IO.Class (liftIO)
import qualified Data.Text.Lazy as T
@ -18,19 +20,35 @@ debug :: Middleware
debug = debugDest $ hPutStrLn stderr . T.unpack
-- | Prints a message using the given callback function for each request.
-- This is not for serious production use- it is inefficient.
-- It immediately consumes a POST body and fills it back in and is otherwise inefficient
debugDest :: (T.Text -> IO ()) -> Middleware
debugDest cb app req = do
body <- consume
(params, files) <- liftIO $ run_ $ enumList 1 body $$ parseRequestBody lbsSink req
params <- if any (requestMethod req ==) ["GET", "HEAD"]
then return []
else do postParams <- liftIO $ allPostParams req body
return $ collectPostParams postParams
let allParams = params ++ (map emptyGetParam $ queryString req)
liftIO $ cb $ T.pack $ concat
[ unpack $ requestMethod req
, " "
, unpack $ rawPathInfo req
, unpack $ rawQueryString req
, "\n"
, (++) "Accept: " $ maybe "" unpack $ lookup "Accept" $ requestHeaders req
, "\n"
, if null params then "" else "Post parameters: " ++ show params ++ "\n"
, if null files then "" else "Post file names: " ++ show (map (fileName . snd) files) ++ "\n"
, show allParams
]
-- we just consumed the body- fill the enumerator back up so it is available again
liftIO $ run_ $ enumList 1 body $$ app req
where
allPostParams req body = run_ $ enumList 1 body $$ parseRequestBody lbsSink req
collectPostParams :: ([Param], [File L.ByteString]) -> [Param]
collectPostParams (postParams, files) = postParams ++
(map (\(k,v) -> (k, S.append "FILE: " (fileName v))) files)
emptyGetParam :: (S.ByteString, Maybe S.ByteString) -> (S.ByteString, S.ByteString)
emptyGetParam (k, Just v) = (k,v)
emptyGetParam (k, Nothing) = (k,"")

View File

@ -8,6 +8,8 @@ module Network.Wai.Parse
, Sink (..)
, lbsSink
, tempFileSink
, Param
, File
, FileInfo (..)
#if TEST
, Bound (..)

View File

@ -10,6 +10,7 @@ import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as S8
import qualified Data.ByteString.Lazy.Char8 as L8
import qualified Data.ByteString.Lazy as L
import qualified Data.Text.Lazy as T
import Control.Arrow
import Network.Wai.Middleware.Jsonp
@ -18,7 +19,7 @@ import Network.Wai.Middleware.Vhost
import Network.Wai.Middleware.Autohead
import Network.Wai.Middleware.MethodOverride
import Network.Wai.Middleware.AcceptOverride
import Network.Wai.Middleware.Debug (debug)
import Network.Wai.Middleware.Debug (debug, debugDest)
import Codec.Compression.GZip (decompress)
import Data.Enumerator (run_, enumList, ($$), Iteratee)
@ -36,11 +37,13 @@ testSuite = testGroup "Network.Wai.Parse"
, testCase "parseQueryString with question mark" caseParseQueryStringQM
, testCase "parseHttpAccept" caseParseHttpAccept
, testCase "parseRequestBody" caseParseRequestBody
{-
, testCase "findBound" caseFindBound
, testCase "sinkTillBound" caseSinkTillBound
, testCase "killCR" caseKillCR
, testCase "killCRLF" caseKillCRLF
, testCase "takeLine" caseTakeLine
-}
, testCase "jsonp" caseJsonp
, testCase "gzip" caseGzip
, testCase "gzip not for MSIE" caseGzipMSIE
@ -165,6 +168,7 @@ toRequest ctype content = SRequest (Request
, requestMethod = "POST"
, rawPathInfo = ""
, rawQueryString = ""
, queryString = []
}) (L.fromChunks [content])
toRequest' :: S8.ByteString -> S8.ByteString -> SRequest
@ -172,6 +176,7 @@ toRequest' ctype content = SRequest (Request
{ requestHeaders = [("Content-Type", ctype)]
}) (L.fromChunks $ map S.singleton $ S.unpack content)
{-
caseFindBound :: Assertion
caseFindBound = do
findBound (S8.pack "def") (S8.pack "abcdefghi") @?=
@ -220,6 +225,7 @@ caseTakeLine = do
helper haystack needle = do
x <- run_ $ enumList 1 [haystack] $$ takeLine
Just needle @=? x
-}
jsonpApp = jsonp $ const $ return $ responseLBS
status200
@ -387,10 +393,11 @@ caseDebugRequestBody = flip runSession debugApp $ do
let req = toRequest "application/x-www-form-urlencoded" "foo=bar&baz=bin"
res <- srequest req
assertStatus 200 res
assertHeader "Parsed" (S8.pack $ show ([("foo", "bar"), ("baz", "bin")], [] :: [Int])) res
where
params = [("foo", "bar"), ("baz", "bin")]
debugOutput = T.pack $ "POST \nAccept: \n" ++ (show params)
debugApp = debug $ \req -> do
x <- parseRequestBody lbsSink req
return $ responseLBS status200
[ ("Parsed", S8.pack $ show x)
] ""
debugApp = debugDest (\t -> liftIO $ assertEqual "debug" debugOutput t) $ \req -> do
return $ responseLBS status200 [ ] ""
{-debugApp = debug $ \req -> do-}
{-return $ responseLBS status200 [ ] ""-}