servant-swagger
servant-swagger copied to clipboard
Helpers for serving swagger.json on server
This is what I've been using:
type WithSwagger api = api :<|> ("swagger.json" :> Get '[JSON] Swagger)
serveWithSwagger :: forall layout. HasServer layout => Swagger -> Proxy layout -> Server layout -> Application
serveWithSwagger spec _ serv = serve (Proxy :: Proxy (WithSwagger layout)) (serv :<|> return spec)
This can be probably generalized so that we won't have to depend on servant-server:
withSwagger :: forall m api application server. Monad m
=> (Proxy (WithSwagger api) -> (server :<|> m Swagger) -> application) -- serve
-> Swagger -> Proxy api -> server -> application
withSwagger serve spec _ server =
serve (Proxy :: Proxy (WithSwagger layout)) (server :<|> return spec)
-- usage example
withSwagger serve (toSwagger api) api server
Since some APIs might use Raw, we probably should prepend swagger endpoint.
Would it be possible for toSwagger to ignore a Swagger in the API, making the above unnecessary ?
Would it be possible for toSwagger to ignore a Swagger in the API, making the above unnecessary ?
That sounds like a good idea. The nice thing is that we can actually document the existence of the Swagger endpoint too.
Prior to Verb, this requires 10 new overlapping instances. With Verb, it'll be two.
The nice thing is that we can actually document the existence of the Swagger endpoint too.
Do we want instance ToSchema Swagger? And do we want that schema definition polluting the list of definitions? Not sure.
I don't mind adding 10 overlapping instances to ignore endpoints ending in Swagger.
Problem
I think this issue actually gives rise to at least these scenarios:
- We don't want
Swaggerendpoint(s) to appear inswagger.json. - We want
Swaggerendpoint(s) to appear, but don't want to pollute definitions. - We want
Swaggerendpoint(s) to appear with an accurate schema.
Solutions
Possible solutions to 1:
- Introduce
WithSwaggerhelpers as show above. - Always ignore
Swaggerenpoints (with specific instances ofHasSwagger). - Provide a helper type family
RemoveEndpoint endpoint api. - Provide a function
removeEndpointand use it to buildtoSwagger_which removesSwaggerendpoints at term-level. - Provide
Ignored anewtype to indicate directly in the API that a type should be ignored byservant-swagger.
Possible solutions to 2:
- Provide an incomplete
ToSchemainstance forSwagger(withexternalDocspointing to the online swagger specification). - Provide a function
truncateSchemato truncate any schema to its type and description/docs, use that to buildtoSwaggerTruncatewhich would truncate schema forSwagger. - Provide a newtype
Truncated ato mark type's schema as truncated in the API.
Possible solutions to 3:
- Just provide a complete
ToSchemainstance forSwagger.
Conclusion
I assume that we want to support all of the scenarios.
I am inclined to this:
- provide a complete
ToSchemainstance forSwagger; - provide a function
truncateSchemato truncate any schema to its type and description/docs, use that to buildtoSwaggerTruncatewhich would truncate schema forSwagger; - provide a function
removeEndpointand use it to buildtoSwagger_which removesSwaggerendpoints at term-level.
@jkarni @dmjio what do you think?
Questions to think about:
- are there any other possible use cases we'd like to support?
- are there other solutions?
- what should be the default recommended case?
I came up with something similar. Some observations:
- I quickly needed to tweak the
Swaggermanually, so my function takes aSwagger -> Swaggerargument. - I think the
hostandbasePathshould be set automatically byserveWithSwagger.
@soenkehahn Swagger -> Swagger makes sense, yes.
I am not sure though how you expect host and basePath to be filled automatically.
Are you suggesting to take those from the request?
Yes, as a small Middleware. As long as servant doesn't offer another way of obtaining this information.
There is servant-swagger-ui, which kind of solves this problem (with a little extra stuff though)?
Hi, Servant-swagger will be moved into the main Servant repo (see : https://github.com/haskell-servant/servant/pull/1475) If this issue is still relevant, would it be possible for you to summit it there? : https://github.com/haskell-servant/servant/issues
Thanks in advance!