{-# LANGUAGE OverloadedStrings #-}

module Network.Wai.Logger.Format (
    apacheFormat
  , apacheFormatBuilder
  ) where

import Blaze.ByteString.Builder
import Blaze.ByteString.Builder.Char8
import Data.ByteString.Char8 ()
import Data.CaseInsensitive
import Data.Maybe
import Data.Monoid
import Network.HTTP.Types
import Network.Wai
import Network.Wai.Logger.Date
import Network.Wai.Logger.IO
import Network.Wai.Logger.Utils

-- | Apache style log format.
apacheFormat :: ZonedDate -> Request -> Status -> Maybe Integer -> [LogStr]
apacheFormat tmstr req st msize = [
    LS addr
  , LB " - - ["
  , LB tmstr
  , LB "] \""
  , LB $ requestMethod req
  , LB " "
  , LB $ rawPathInfo req
  , LB " "
  , LS $ show . httpVersion $ req
  , LB "\" "
  , LS . show . statusCode $ st
  , LB " "
  , LS $ maybe "-" show msize
  , LB " \""
  , LB $ lookupRequestField' "referer" req
  , LB "\" \""
  , LB $ lookupRequestField' "user-agent" req
  , LB "\"\n"
  ]
  where
    addr = showSockAddr (remoteHost req)

lookupRequestField' :: CI Ascii -> Request -> Ascii
lookupRequestField' k req = fromMaybe "" . lookup k $ requestHeaders req

-- | Apache style log format with 'Builder'. This is experimental.
apacheFormatBuilder :: ZonedDate -> Request -> Status -> Maybe Integer -> Builder
apacheFormatBuilder tmstr req status msize =
      st addr
  +++ bs " - - ["
  +++ bs tmstr
  +++ bs "] \""
  +++ bs (requestMethod req)
  +++ bs " "
  +++ bs (rawPathInfo req)
  +++ bs " "
  +++ st (show (httpVersion req))
  +++ bs "\" "
  +++ st (show (statusCode status))
  +++ bs " "
  +++ st (maybe "-" show msize)
  +++ bs " \""
  +++ bs (lookupRequestField' "referer" req)
  +++ bs "\" \""
  +++ bs (lookupRequestField' "user-agent" req)
  +++ bs "\"\n"
  where
    addr = showSockAddr (remoteHost req)
    st = fromString
    bs = fromByteString
    (+++) = mappend