{-# LANGUAGE OverloadedStrings #-} {-| Module : Test.Swagger.Types Description : Types used for other swagger-test modules Copyright : (c) Rodrigo Setti, 2017 License : BSD3 Maintainer : rodrigosetti@gmail.com Stability : experimental Portability : POSIX This module exposes some types that ure used across other modules of swagger-test. -} module Test.Swagger.Types (FullyQualifiedHost , Seed , Size , NormalizedSwagger , getSwagger , OperationId , HttpHeader , Headers , HttpRequest(..) , HttpResponse(..) , refToMaybe) where import Control.Arrow import Control.Lens hiding ((.=)) import Data.Aeson import qualified Data.ByteString.Lazy as LBS import Data.CaseInsensitive import Data.Generics import qualified Data.HashMap.Lazy as HM import qualified Data.HashMap.Strict.InsOrd as M import Data.Monoid ((<>)) import Data.Swagger hiding (prependPath) import qualified Data.Text as T import Data.Text.Encoding import Network.HTTP.Types import System.FilePath.Posix -- |The FullyQualifiedHost contains the scheme (i.e. http://), hostname and port. type FullyQualifiedHost = String type Seed = Int type Size = Int type OperationId = T.Text type HttpHeader = (CI T.Text, T.Text) type Headers = [HttpHeader] data HttpRequest = HttpRequest { requestHost :: Maybe FullyQualifiedHost , requestMethod :: Method , requestPath :: T.Text , requestQuery :: QueryText , requestHeaders :: Headers , requestBody :: Maybe LBS.ByteString } deriving (Eq, Show) instance ToJSON HttpRequest where toJSON r = object [ "host" .= toJSON (requestHost r) , "method" .= toJSON (decodeUtf8 $ requestMethod r) , "path" .= toJSON (requestPath r) , "query" .= toJSON (requestQuery r) , "headers" .= toJSON headersMap , "body" .= toJSON (decodeUtf8 . LBS.toStrict <$> requestBody r) ] where headersMap = HM.fromList $ first original <$> requestHeaders r data HttpResponse = HttpResponse { responseHttpVersion :: HttpVersion , responseStatus :: Status , responseHeaders :: Headers , responseBody :: Maybe LBS.ByteString } deriving (Eq, Show) instance ToJSON HttpResponse where toJSON r = object [ "version" .= object [ "major" .= toJSON (httpMajor ver) , "minor" .= toJSON (httpMinor ver)] , "status" .= object [ "code" .= toJSON (statusCode st) , "message" .= toJSON (decodeUtf8 $ statusMessage st) ] , "headers" .= toJSON headersMap , "body" .= toJSON (decodeUtf8 . LBS.toStrict <$> responseBody r) ] where ver = responseHttpVersion r st = responseStatus r headersMap = M.fromList $ first original <$> responseHeaders r newtype NormalizedSwagger = Normalized { getSwagger :: Swagger } instance FromJSON NormalizedSwagger where parseJSON = fmap (Normalized . resolveReferences . prependBase) . parseJSON where prependBase :: Swagger -> Swagger prependBase s = maybe s (`prependPath` s) (s ^. basePath) & basePath .~ Nothing -- |Replace all references with inlines resolveReferences :: Swagger -> Swagger resolveReferences s = everywhere' (mkT resolveSchema) $ everywhere' (mkT resolveParam) s -- NOTE: we need to use the top-down everywhere variant for this to work as intented where resolveParam :: Referenced Param -> Referenced Param resolveParam i@Inline {} = i resolveParam (Ref (Reference r)) = maybe (error $ "undefied schema: " <> T.unpack r) Inline $ M.lookup r $ s ^. parameters resolveSchema :: Referenced Schema -> Referenced Schema resolveSchema i@Inline {} = i resolveSchema (Ref (Reference r)) = maybe (error $ "undefied schema: " <> T.unpack r) Inline $ M.lookup r $ s ^. definitions prependPath :: FilePath -> Swagger -> Swagger prependPath path = paths %~ M.mapKeys (\x -> path dropWhile (== '/') x) -- |Transform a reference into a Just value if is inline, Nothing, otherwise refToMaybe :: Referenced a -> Maybe a refToMaybe (Inline i) = Just i refToMaybe (Ref _) = Nothing