module Airship.Internal.Helpers where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
import Data.ByteString (ByteString)
import Data.Maybe
#if __GLASGOW_HASKELL__ < 710
import Data.Monoid
#endif
import Data.Text (Text, intercalate)
import Data.Text.Encoding
import Data.Time (getCurrentTime)
import Network.HTTP.Media
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wai as Wai
import System.Random
import Airship.Internal.Decision
import Airship.Resource
import Airship.Types
import Airship.Internal.Route
contentTypeMatches :: [MediaType] -> Handler s m Bool
contentTypeMatches validTypes = do
headers <- requestHeaders <$> request
let cType = lookup HTTP.hContentType headers
return $ case cType of
Nothing -> True
Just t -> isJust $ matchAccept validTypes t
fromWaiRequest :: Wai.Request -> Request IO
fromWaiRequest req = Request
{ requestMethod = Wai.requestMethod req
, httpVersion = Wai.httpVersion req
, rawPathInfo = Wai.rawPathInfo req
, rawQueryString = Wai.rawQueryString req
, requestHeaders = Wai.requestHeaders req
, isSecure = Wai.isSecure req
, remoteHost = Wai.remoteHost req
, pathInfo = Wai.pathInfo req
, queryString = Wai.queryString req
, requestBody = Wai.requestBody req
, requestBodyLength = Wai.requestBodyLength req
, requestHeaderHost = Wai.requestHeaderHost req
, requestHeaderRange = Wai.requestHeaderRange req
}
toWaiResponse :: Response IO -> ByteString -> ByteString -> Wai.Response
toWaiResponse Response{..} trace quip =
Wai.responseBuilder _responseStatus headers (fromBody _responseBody)
where fromBody (ResponseBuilder b) = b
fromBody _ = mempty
headers = _responseHeaders ++
[("Airship-Trace", trace)] ++
[("Airship-Quip", quip)]
resourceToWai :: RoutingSpec s IO () -> Resource s IO -> s -> Wai.Application
resourceToWai routes resource404 s req respond = do
let routeMapping = runRouter routes
pInfo = Wai.pathInfo req
airshipReq = fromWaiRequest req
(resource, params') = route routeMapping pInfo resource404
nowTime <- getCurrentTime
quip <- getQuip
(response, trace) <- eitherResponse nowTime params' airshipReq s (flow resource)
let traceHeaderValue = traceHeader trace
respond (toWaiResponse response traceHeaderValue quip)
getQuip :: IO ByteString
getQuip = do
idx <- randomRIO (0, length quips 1)
return $ quips !! idx
where quips = [ "never breaks eye contact"
, "blame me if inappropriate"
, "firm pat on the back"
, "sharkfed"
, "$300,000 worth of cows"
, "RB_GC_GUARD"
, "evacuation not done in time"
, "javascript doesn't have integers"
, "WARNING: ulimit -n is 1024"
]
traceHeader :: [Text] -> ByteString
traceHeader = encodeUtf8 . intercalate ","