git.iko.soy/typeable/openapi3
on master help sign in
rename `data Swagger` to `data OpenApi`
03b5707Paweł Nosal
examples/hackage.hs+2−2
@@ -47,12 +47,12 @@ data UserDetailed = UserDetailed
47newtype Package = Package { packageName :: Text }
47newtype Package = Package { packageName :: Text }
48 deriving (Generic, ToSchema)
48 deriving (Generic, ToSchema)
49
49
50−hackageSwagger :: Swagger
50+hackageSwagger :: OpenApi
51hackageSwagger = spec & components.schemas .~ defs
51hackageSwagger = spec & components.schemas .~ defs
52 where
52 where
53 (defs, spec) = runDeclare declareHackageSwagger mempty
53 (defs, spec) = runDeclare declareHackageSwagger mempty
54
54
55−declareHackageSwagger :: Declare (Definitions Schema) Swagger
55+declareHackageSwagger :: Declare (Definitions Schema) OpenApi
56declareHackageSwagger = do
56declareHackageSwagger = do
57 -- param schemas
57 -- param schemas
58 let usernameParamSchema = toParamSchema (Proxy :: Proxy Username)
58 let usernameParamSchema = toParamSchema (Proxy :: Proxy Username)
src/Data/OpenApi.hs+6−6
@@ -37,7 +37,7 @@ module Data.OpenApi (
37 module Data.OpenApi.Schema.Validation,
37 module Data.OpenApi.Schema.Validation,
38
38
39 -- * Swagger specification
39 -- * Swagger specification
40− Swagger(..),
40+ OpenApi(..),
41 Server(..),
41 Server(..),
42 ServerVariable(..),
42 ServerVariable(..),
43 Components(..),
43 Components(..),
@@ -152,7 +152,7 @@ import Data.OpenApi.Internal
152--
152--
153-- In this library you can use @'mempty'@ for a default/empty value. For instance:
153-- In this library you can use @'mempty'@ for a default/empty value. For instance:
154--
154--
155−-- >>> BSL.putStrLn $ encode (mempty :: Swagger)
155+-- >>> BSL.putStrLn $ encode (mempty :: OpenApi)
156-- {"openapi":"3.0.0","info":{"version":"","title":""},"components":{}}
156-- {"openapi":"3.0.0","info":{"version":"","title":""},"components":{}}
157--
157--
158-- As you can see some spec properties (e.g. @"version"@) are there even when the spec is empty.
158-- As you can see some spec properties (e.g. @"version"@) are there even when the spec is empty.
@@ -173,14 +173,14 @@ import Data.OpenApi.Internal
173--
173--
174-- @
174-- @
175-- \-\- /account subAPI specification
175-- \-\- /account subAPI specification
176−-- accountAPI :: Swagger
176+-- accountAPI :: OpenApi
177--
177--
178-- \-\- /task subAPI specification
178-- \-\- /task subAPI specification
179−-- taskAPI :: Swagger
179+-- taskAPI :: OpenApi
180--
180--
181-- \-\- while API specification is just a combination
181-- \-\- while API specification is just a combination
182-- \-\- of subAPIs' specifications
182-- \-\- of subAPIs' specifications
183−-- api :: Swagger
183+-- api :: OpenApi
184-- api = accountAPI <> taskAPI
184-- api = accountAPI <> taskAPI
185-- @
185-- @
186
186
@@ -193,7 +193,7 @@ import Data.OpenApi.Internal
193-- make it fairly simple to construct/modify any part of the specification:
193-- make it fairly simple to construct/modify any part of the specification:
194--
194--
195-- >>> :{
195-- >>> :{
196−-- BSL.putStrLn $ encode $ (mempty :: Swagger)
196+-- BSL.putStrLn $ encode $ (mempty :: OpenApi)
197-- & components . schemas .~ [ ("User", mempty & type_ ?~ SwaggerString) ]
197-- & components . schemas .~ [ ("User", mempty & type_ ?~ SwaggerString) ]
198-- & paths .~
198-- & paths .~
199-- [ ("/user", mempty & get ?~ (mempty
199-- [ ("/user", mempty & get ?~ (mempty
src/Data/OpenApi/Internal.hs+15−15
@@ -65,38 +65,38 @@ import Data.OpenApi.Internal.AesonUtils (sopSwaggerGenericToEncoding)
65type Definitions = InsOrdHashMap Text
65type Definitions = InsOrdHashMap Text
66
66
67-- | This is the root document object for the API specification.
67-- | This is the root document object for the API specification.
68−data Swagger = Swagger
68+data OpenApi = OpenApi
69 { -- | Provides metadata about the API.
69 { -- | Provides metadata about the API.
70 -- The metadata can be used by the clients if needed.
70 -- The metadata can be used by the clients if needed.
71− _swaggerInfo :: Info
71+ _openApiInfo :: Info
72
72
73 -- | An array of Server Objects, which provide connectivity information
73 -- | An array of Server Objects, which provide connectivity information
74 -- to a target server. If the servers property is not provided, or is an empty array,
74 -- to a target server. If the servers property is not provided, or is an empty array,
75 -- the default value would be a 'Server' object with a url value of @/@.
75 -- the default value would be a 'Server' object with a url value of @/@.
76− , _swaggerServers :: [Server]
76+ , _openApiServers :: [Server]
77
77
78 -- | The available paths and operations for the API.
78 -- | The available paths and operations for the API.
79− , _swaggerPaths :: InsOrdHashMap FilePath PathItem
79+ , _openApiPaths :: InsOrdHashMap FilePath PathItem
80
80
81 -- | An element to hold various schemas for the specification.
81 -- | An element to hold various schemas for the specification.
82− , _swaggerComponents :: Components
82+ , _openApiComponents :: Components
83
83
84 -- | A declaration of which security mechanisms can be used across the API.
84 -- | A declaration of which security mechanisms can be used across the API.
85 -- The list of values includes alternative security requirement objects that can be used.
85 -- The list of values includes alternative security requirement objects that can be used.
86 -- Only one of the security requirement objects need to be satisfied to authorize a request.
86 -- Only one of the security requirement objects need to be satisfied to authorize a request.
87 -- Individual operations can override this definition.
87 -- Individual operations can override this definition.
88 -- To make security optional, an empty security requirement can be included in the array.
88 -- To make security optional, an empty security requirement can be included in the array.
89− , _swaggerSecurity :: [SecurityRequirement]
89+ , _openApiSecurity :: [SecurityRequirement]
90
90
91 -- | A list of tags used by the specification with additional metadata.
91 -- | A list of tags used by the specification with additional metadata.
92 -- The order of the tags can be used to reflect on their order by the parsing tools.
92 -- The order of the tags can be used to reflect on their order by the parsing tools.
93 -- Not all tags that are used by the 'Operation' Object must be declared.
93 -- Not all tags that are used by the 'Operation' Object must be declared.
94 -- The tags that are not declared MAY be organized randomly or based on the tools' logic.
94 -- The tags that are not declared MAY be organized randomly or based on the tools' logic.
95 -- Each tag name in the list MUST be unique.
95 -- Each tag name in the list MUST be unique.
96− , _swaggerTags :: InsOrdHashSet Tag
96+ , _openApiTags :: InsOrdHashSet Tag
97
97
98 -- | Additional external documentation.
98 -- | Additional external documentation.
99− , _swaggerExternalDocs :: Maybe ExternalDocs
99+ , _openApiExternalDocs :: Maybe ExternalDocs
100 } deriving (Eq, Show, Generic, Data, Typeable)
100 } deriving (Eq, Show, Generic, Data, Typeable)
101
101
102-- | The object provides metadata about the API.
102-- | The object provides metadata about the API.
@@ -936,7 +936,7 @@ deriveGeneric ''MediaTypeObject
936deriveGeneric ''Responses
936deriveGeneric ''Responses
937deriveGeneric ''SecurityScheme
937deriveGeneric ''SecurityScheme
938deriveGeneric ''Schema
938deriveGeneric ''Schema
939−deriveGeneric ''Swagger
939+deriveGeneric ''OpenApi
940deriveGeneric ''Example
940deriveGeneric ''Example
941deriveGeneric ''Encoding
941deriveGeneric ''Encoding
942deriveGeneric ''Link
942deriveGeneric ''Link
@@ -945,9 +945,9 @@ deriveGeneric ''Link
945-- Monoid instances
945-- Monoid instances
946-- =======================================================================
946-- =======================================================================
947
947
948−instance Semigroup Swagger where
948+instance Semigroup OpenApi where
949 (<>) = genericMappend
949 (<>) = genericMappend
950−instance Monoid Swagger where
950+instance Monoid OpenApi where
951 mempty = genericMempty
951 mempty = genericMempty
952 mappend = (<>)
952 mappend = (<>)
953
953
@@ -1243,9 +1243,9 @@ instance ToJSON SecuritySchemeType where
1243 , "openIdConnectUrl" .= url
1243 , "openIdConnectUrl" .= url
1244 ]
1244 ]
1245
1245
1246−instance ToJSON Swagger where
1246+instance ToJSON OpenApi where
1247 toJSON a = sopSwaggerGenericToJSON a &
1247 toJSON a = sopSwaggerGenericToJSON a &
1248− if InsOrdHashMap.null (_swaggerPaths a)
1248+ if InsOrdHashMap.null (_openApiPaths a)
1249 then (<+> object ["paths" .= object []])
1249 then (<+> object ["paths" .= object []])
1250 else id
1250 else id
1251 toEncoding = sopSwaggerGenericToEncoding
1251 toEncoding = sopSwaggerGenericToEncoding
@@ -1386,7 +1386,7 @@ instance FromJSON SecuritySchemeType where
1386 _ -> empty
1386 _ -> empty
1387 parseJSON _ = empty
1387 parseJSON _ = empty
1388
1388
1389−instance FromJSON Swagger where
1389+instance FromJSON OpenApi where
1390 parseJSON = sopSwaggerGenericParseJSON
1390 parseJSON = sopSwaggerGenericParseJSON
1391
1391
1392instance FromJSON Server where
1392instance FromJSON Server where
@@ -1526,7 +1526,7 @@ instance HasSwaggerAesonOptions SecurityScheme where
1526 swaggerAesonOptions _ = mkSwaggerAesonOptions "securityScheme" & saoSubObject ?~ "type"
1526 swaggerAesonOptions _ = mkSwaggerAesonOptions "securityScheme" & saoSubObject ?~ "type"
1527instance HasSwaggerAesonOptions Schema where
1527instance HasSwaggerAesonOptions Schema where
1528 swaggerAesonOptions _ = mkSwaggerAesonOptions "schema" & saoSubObject ?~ "paramSchema"
1528 swaggerAesonOptions _ = mkSwaggerAesonOptions "schema" & saoSubObject ?~ "paramSchema"
1529−instance HasSwaggerAesonOptions Swagger where
1529+instance HasSwaggerAesonOptions OpenApi where
1530 swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.0")]
1530 swaggerAesonOptions _ = mkSwaggerAesonOptions "swagger" & saoAdditionalPairs .~ [("openapi", "3.0.0")]
1531instance HasSwaggerAesonOptions Example where
1531instance HasSwaggerAesonOptions Example where
1532 swaggerAesonOptions _ = mkSwaggerAesonOptions "example"
1532 swaggerAesonOptions _ = mkSwaggerAesonOptions "example"
src/Data/OpenApi/Lens.hs+1−1
@@ -26,7 +26,7 @@ import Data.Text (Text)
26
26
27-- * Classy lenses
27-- * Classy lenses
28
28
29−makeFields ''Swagger
29+makeFields ''OpenApi
30makeFields ''Components
30makeFields ''Components
31makeFields ''Server
31makeFields ''Server
32makeFields ''RequestBody
32makeFields ''RequestBody
src/Data/OpenApi/Operation.hs+13−13
@@ -59,10 +59,10 @@ import qualified Data.HashSet.InsOrd as InsOrdHS
59-- | Prepend path piece to all operations of the spec.
59-- | Prepend path piece to all operations of the spec.
60-- Leading and trailing slashes are trimmed/added automatically.
60-- Leading and trailing slashes are trimmed/added automatically.
61--
61--
62−-- >>> let api = (mempty :: Swagger) & paths .~ [("/info", mempty)]
62+-- >>> let api = (mempty :: OpenApi) & paths .~ [("/info", mempty)]
63-- >>> BSL.putStrLn $ encode $ prependPath "user/{user_id}" api ^. paths
63-- >>> BSL.putStrLn $ encode $ prependPath "user/{user_id}" api ^. paths
64-- {"/user/{user_id}/info":{}}
64-- {"/user/{user_id}/info":{}}
65−prependPath :: FilePath -> Swagger -> Swagger
65+prependPath :: FilePath -> OpenApi -> OpenApi
66prependPath path = paths %~ InsOrdHashMap.mapKeys (path </>)
66prependPath path = paths %~ InsOrdHashMap.mapKeys (path </>)
67 where
67 where
68 x </> y = case trim y of
68 x </> y = case trim y of
@@ -72,7 +72,7 @@ prependPath path = paths %~ InsOrdHashMap.mapKeys (path </>)
72 trim = dropWhile (== '/') . dropWhileEnd (== '/')
72 trim = dropWhile (== '/') . dropWhileEnd (== '/')
73
73
74-- | All operations of a Swagger spec.
74-- | All operations of a Swagger spec.
75−allOperations :: Traversal' Swagger Operation
75+allOperations :: Traversal' OpenApi Operation
76allOperations = paths.traverse.template
76allOperations = paths.traverse.template
77
77
78-- | @'operationsOf' sub@ will traverse only those operations
78-- | @'operationsOf' sub@ will traverse only those operations
@@ -80,13 +80,13 @@ allOperations = paths.traverse.template
80-- by both path and method.
80-- by both path and method.
81--
81--
82-- >>> let ok = (mempty :: Operation) & at 200 ?~ "OK"
82-- >>> let ok = (mempty :: Operation) & at 200 ?~ "OK"
83−-- >>> let api = (mempty :: Swagger) & paths .~ [("/user", mempty & get ?~ ok & post ?~ ok)]
83+-- >>> let api = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ ok & post ?~ ok)]
84−-- >>> let sub = (mempty :: Swagger) & paths .~ [("/user", mempty & get ?~ mempty)]
84+-- >>> let sub = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ mempty)]
85-- >>> BSL.putStrLn $ encode api
85-- >>> BSL.putStrLn $ encode api
86-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}
86-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}
87-- >>> BSL.putStrLn $ encode $ api & operationsOf sub . at 404 ?~ "Not found"
87-- >>> BSL.putStrLn $ encode $ api & operationsOf sub . at 404 ?~ "Not found"
88-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"404":{"description":"Not found"},"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}
88-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"404":{"description":"Not found"},"200":{"description":"OK"}}},"post":{"responses":{"200":{"description":"OK"}}}}},"components":{}}
89−operationsOf :: Swagger -> Traversal' Swagger Operation
89+operationsOf :: OpenApi -> Traversal' OpenApi Operation
90operationsOf sub = paths.itraversed.withIndex.subops
90operationsOf sub = paths.itraversed.withIndex.subops
91 where
91 where
92 -- | Traverse operations that correspond to paths and methods of the sub API.
92 -- | Traverse operations that correspond to paths and methods of the sub API.
@@ -108,12 +108,12 @@ operationsOf sub = paths.itraversed.withIndex.subops
108-- @
108-- @
109-- 'applyTags' = 'applyTagsFor' 'allOperations'
109-- 'applyTags' = 'applyTagsFor' 'allOperations'
110-- @
110-- @
111−applyTags :: [Tag] -> Swagger -> Swagger
111+applyTags :: [Tag] -> OpenApi -> OpenApi
112applyTags = applyTagsFor allOperations
112applyTags = applyTagsFor allOperations
113
113
114-- | Apply tags to a part of Swagger spec and update the global
114-- | Apply tags to a part of Swagger spec and update the global
115-- list of tags.
115-- list of tags.
116−applyTagsFor :: Traversal' Swagger Operation -> [Tag] -> Swagger -> Swagger
116+applyTagsFor :: Traversal' OpenApi Operation -> [Tag] -> OpenApi -> OpenApi
117applyTagsFor ops ts swag = swag
117applyTagsFor ops ts swag = swag
118 & ops . tags %~ (<> InsOrdHS.fromList (map _tagName ts))
118 & ops . tags %~ (<> InsOrdHS.fromList (map _tagName ts))
119 & tags %~ (<> InsOrdHS.fromList ts)
119 & tags %~ (<> InsOrdHS.fromList ts)
@@ -141,13 +141,13 @@ declareResponse cType proxy = do
141--
141--
142-- Example:
142-- Example:
143--
143--
144−-- >>> let api = (mempty :: Swagger) & paths .~ [("/user", mempty & get ?~ mempty)]
144+-- >>> let api = (mempty :: OpenApi) & paths .~ [("/user", mempty & get ?~ mempty)]
145-- >>> let res = declareResponse "application/json" (Proxy :: Proxy Day)
145-- >>> let res = declareResponse "application/json" (Proxy :: Proxy Day)
146-- >>> BSL.putStrLn $ encode $ api & setResponse 200 res
146-- >>> BSL.putStrLn $ encode $ api & setResponse 200 res
147-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Day"}}},"description":""}}}}},"components":{"schemas":{"Day":{"example":"2016-07-22","format":"date","type":"string"}}}}
147-- {"openapi":"3.0.0","info":{"version":"","title":""},"paths":{"/user":{"get":{"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Day"}}},"description":""}}}}},"components":{"schemas":{"Day":{"example":"2016-07-22","format":"date","type":"string"}}}}
148--
148--
149-- See also @'setResponseWith'@.
149-- See also @'setResponseWith'@.
150−setResponse :: HttpStatusCode -> Declare (Definitions Schema) Response -> Swagger -> Swagger
150+setResponse :: HttpStatusCode -> Declare (Definitions Schema) Response -> OpenApi -> OpenApi
151setResponse = setResponseFor allOperations
151setResponse = setResponseFor allOperations
152
152
153-- | Set or update response for all operations.
153-- | Set or update response for all operations.
@@ -161,7 +161,7 @@ setResponse = setResponseFor allOperations
161-- @
161-- @
162--
162--
163-- See also @'setResponse'@.
163-- See also @'setResponse'@.
164−setResponseWith :: (Response -> Response -> Response) -> HttpStatusCode -> Declare (Definitions Schema) Response -> Swagger -> Swagger
164+setResponseWith :: (Response -> Response -> Response) -> HttpStatusCode -> Declare (Definitions Schema) Response -> OpenApi -> OpenApi
165setResponseWith = setResponseForWith allOperations
165setResponseWith = setResponseForWith allOperations
166
166
167-- | Set response for specified operations.
167-- | Set response for specified operations.
@@ -170,7 +170,7 @@ setResponseWith = setResponseForWith allOperations
170-- If the response already exists it will be overwritten.
170-- If the response already exists it will be overwritten.
171--
171--
172-- See also @'setResponseForWith'@.
172-- See also @'setResponseForWith'@.
173−setResponseFor :: Traversal' Swagger Operation -> HttpStatusCode -> Declare (Definitions Schema) Response -> Swagger -> Swagger
173+setResponseFor :: Traversal' OpenApi Operation -> HttpStatusCode -> Declare (Definitions Schema) Response -> OpenApi -> OpenApi
174setResponseFor ops code dres swag = swag
174setResponseFor ops code dres swag = swag
175 & components.schemas %~ (<> defs)
175 & components.schemas %~ (<> defs)
176 & ops . at code ?~ Inline res
176 & ops . at code ?~ Inline res
@@ -184,7 +184,7 @@ setResponseFor ops code dres swag = swag
184-- then just the new response is used.
184-- then just the new response is used.
185--
185--
186-- See also @'setResponseFor'@.
186-- See also @'setResponseFor'@.
187−setResponseForWith :: Traversal' Swagger Operation -> (Response -> Response -> Response) -> HttpStatusCode -> Declare (Definitions Schema) Response -> Swagger -> Swagger
187+setResponseForWith :: Traversal' OpenApi Operation -> (Response -> Response -> Response) -> HttpStatusCode -> Declare (Definitions Schema) Response -> OpenApi -> OpenApi
188setResponseForWith ops f code dres swag = swag
188setResponseForWith ops f code dres swag = swag
189 & components.schemas %~ (<> defs)
189 & components.schemas %~ (<> defs)
190 & ops . at code %~ Just . Inline . combine
190 & ops . at code %~ Just . Inline . combine
src/Data/OpenApi/Optics.hs+2−2
@@ -22,7 +22,7 @@
22-- Example from the "Data.OpenApi" module using @optics@:
22-- Example from the "Data.OpenApi" module using @optics@:
23--
23--
24-- >>> :{
24-- >>> :{
25−-- BSL.putStrLn $ encode $ (mempty :: Swagger)
25+-- BSL.putStrLn $ encode $ (mempty :: OpenApi)
26-- & #components % #schemas .~ [ ("User", mempty & #type ?~ SwaggerString) ]
26-- & #components % #schemas .~ [ ("User", mempty & #type ?~ SwaggerString) ]
27-- & #paths .~
27-- & #paths .~
28-- [ ("/user", mempty & #get ?~ (mempty
28-- [ ("/user", mempty & #get ?~ (mempty
@@ -65,7 +65,7 @@ import Optics.TH
65
65
66-- Lenses
66-- Lenses
67
67
68−makeFieldLabels ''Swagger
68+makeFieldLabels ''OpenApi
69makeFieldLabels ''Components
69makeFieldLabels ''Components
70makeFieldLabels ''Server
70makeFieldLabels ''Server
71makeFieldLabels ''ServerVariable
71makeFieldLabels ''ServerVariable
test/Data/OpenApiSpec.hs+4−4
@@ -42,9 +42,9 @@ spec = do
42 context "Todo Example" $ swaggerExample <=> swaggerExampleJSON
42 context "Todo Example" $ swaggerExample <=> swaggerExampleJSON
43 context "PetStore Example" $ do
43 context "PetStore Example" $ do
44 it "decodes successfully" $ do
44 it "decodes successfully" $ do
45− fromJSON petstoreExampleJSON `shouldSatisfy` (\x -> case x of Success (_ :: Swagger) -> True; _ -> False)
45+ fromJSON petstoreExampleJSON `shouldSatisfy` (\x -> case x of Success (_ :: OpenApi) -> True; _ -> False)
46 it "roundtrips: fmap toJSON . fromJSON" $ do
46 it "roundtrips: fmap toJSON . fromJSON" $ do
47− (toJSON :: Swagger -> Value) <$> fromJSON petstoreExampleJSON `shouldBe` Success petstoreExampleJSON
47+ (toJSON :: OpenApi -> Value) <$> fromJSON petstoreExampleJSON `shouldBe` Success petstoreExampleJSON
48
48
49main :: IO ()
49main :: IO ()
50main = hspec spec
50main = hspec spec
@@ -531,7 +531,7 @@ oAuth2SecurityDefinitionsExampleJSON = [aesonQQ|
531-- Swagger object
531-- Swagger object
532-- =======================================================================
532-- =======================================================================
533
533
534−emptyPathsFieldExample :: Swagger
534+emptyPathsFieldExample :: OpenApi
535emptyPathsFieldExample = mempty
535emptyPathsFieldExample = mempty
536
536
537emptyPathsFieldExampleJSON :: Value
537emptyPathsFieldExampleJSON :: Value
@@ -544,7 +544,7 @@ emptyPathsFieldExampleJSON = [aesonQQ|
544}
544}
545|]
545|]
546
546
547−swaggerExample :: Swagger
547+swaggerExample :: OpenApi
548swaggerExample = mempty
548swaggerExample = mempty
549 -- & basePath ?~ "/"
549 -- & basePath ?~ "/"
550 -- & schemes ?~ [Http]
550 -- & schemes ?~ [Http]