-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Intergate Swagger UI Hosting as Ktor Feature #453
Comments
Some of the concerns that I have with this code base as it is is that it generates all of the schemas from kotlin data classes and expects that some JSON content negotiation feature be installed (ie. Jackson or Gson). The downside of this is that you are unable to define your JSON schemas externally for objects easily (for example, you would like to put custom descriptions on fields and apply JSON schema validation). Currently, the way the feature is written the typealias ModelName = String
typealias PropertyName = String
typealias Path = String
typealias Definitions = MutableMap<ModelName, ModelData>
typealias Paths = MutableMap<Path, Methods>
typealias MethodName = String
typealias HttpStatus = String
typealias Methods = MutableMap<MethodName, Operation>
class Swagger {
val swagger = "2.0"
var info: Information? = null
val paths: Paths = mutableMapOf()
val definitions: Definitions = mutableMapOf()
}
class Information(
val description: String? = null,
val version: String? = null,
val title: String? = null,
val contact: Contact? = null
)
data class Tag(
val name: String
)
class Contact(
val name: String? = null,
val url: String? = null,
val email: String? = null
)
class Operation(
metadata: Metadata,
val responses: Map<HttpStatus, Response>,
val parameters: List<Parameter>,
location: Location,
group: Group?,
method: HttpMethod,
locationType: KClass<*>,
entityType: KClass<*>
) {
val tags = group?.toList()
val summary = metadata.summary ?: "${method.value} ${location.path}"
}
class ModelData(val properties: Map<PropertyName, Property>) The above structure generates the JSON that looks like the following when GSON is installed. {
"swagger": "2.0",
"info": {
"description": "This is a sample which combines [ktor](https://github.com/Kotlin/ktor) with [swaggerUi](https://swagger.io/). You find the sources on [github](https://github.com/nielsfalk/ktor-swagger)",
"version": "0.1",
"title": "sample api implemented in ktor",
"contact": {
"name": "Niels Falk",
"url": "https://nielsfalk.de"
}
},
"paths": {
"/pets": {
"get": {
"tags": [
{
"name": "pet operations"
}
],
"summary": "all",
"responses": {
"200": {
"description": "PetsModel",
"schema": {
"$ref": "#/definitions/PetsModel"
}
}
},
"parameters": []
},
"post": {
"tags": [
{
"name": "pet operations"
}
],
"summary": "create",
"responses": {
"201": {
"description": "PetModel",
"schema": {
"$ref": "#/definitions/PetModel"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"description": "PetModel",
"required": true,
"schema": {
"$ref": "#/definitions/PetModel"
}
}
]
}
},
"/pets/{id}": {
"get": {
"tags": [
{
"name": "pet operations"
}
],
"summary": "find",
"responses": {
"200": {
"description": "PetModel",
"schema": {
"$ref": "#/definitions/PetModel"
}
},
"404": {
"description": "Not Found"
}
},
"parameters": [
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "integer",
"format": "int32"
}
]
},
"put": {
"tags": [
{
"name": "pet operations"
}
],
"summary": "update",
"responses": {
"200": {
"description": "PetModel",
"schema": {
"$ref": "#/definitions/PetModel"
}
},
"404": {
"description": "Not Found"
}
},
"parameters": [
{
"name": "body",
"in": "body",
"description": "PetModel",
"required": true,
"schema": {
"$ref": "#/definitions/PetModel"
}
},
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "integer",
"format": "int32"
}
]
},
"delete": {
"tags": [
{
"name": "pet operations"
}
],
"summary": "delete",
"responses": {
"200": {
"description": "OK"
},
"404": {
"description": "Not Found"
}
},
"parameters": [
{
"name": "id",
"in": "path",
"description": "id",
"required": true,
"type": "integer",
"format": "int32"
}
]
}
},
"/request/info": {
"get": {
"tags": [
{
"name": "debug"
}
],
"summary": "GET /request/info",
"responses": {
"200": {
"description": "OK"
}
},
"parameters": []
}
},
"/request/withQueryParameter": {
"get": {
"tags": [
{
"name": "debug"
}
],
"summary": "GET /request/withQueryParameter",
"responses": {
"200": {
"description": "OK"
}
},
"parameters": [
{
"name": "mandatoryParameter",
"in": "query",
"description": "mandatoryParameter",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "optionalParameter",
"in": "query",
"description": "optionalParameter",
"required": false,
"type": "string"
}
]
}
},
"/request/withHeader": {
"get": {
"tags": [
{
"name": "debug"
}
],
"summary": "GET /request/withHeader",
"responses": {
"200": {
"description": "OK"
}
},
"parameters": [
{
"name": "mandatoryHeader",
"in": "header",
"description": "mandatoryHeader",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "optionalHeader",
"in": "header",
"description": "optionalHeader",
"required": false,
"type": "string"
}
]
}
}
},
"definitions": {
"PetsModel": {
"properties": {
"pets": {
"type": "array",
"items": {
"description": "PetModel",
"$ref": "#/definitions/PetModel"
}
}
}
},
"PetModel": {
"properties": {
"id": {
"type": "integer",
"format": "int32"
},
"name": {
"type": "string"
}
}
}
}
} You could fix this perhaps by defining: typealias Definitions = MutableMap<ModelName, Any> And allowing a user to define either a class or pass a custom schema as a string. Another component that is missing from this example that I'd really like in my application is some sort of JSON Schema validation before the content is deserialized by the content negotiator. |
I'm looking for some feedback from @cy6erGn0m or @orangy before I proceed with a PR. |
Are there plans to release this? |
@orangefiredragon It's currently released here: I'd love to integrate it officially. Currently the project is 90% developed for my own use case at my company. The API is also pretty fluid currently as I'm still figuring out where we are missing things/need new functionality. But in its current state it's very functional. |
I'd love to see this integrated into Ktor. Automatic API docs is great! |
Really hope to see the official GO from Ktor crew. |
@JLLeitschuh @nielsfalk I tried the example code at the top of this issue thread, but I'm running into "$ref: must be a string (JSON-Ref)" errors whenever I click to expand any of the operations in the Swagger UI page. I'm trying to use ktor-swagger with Ktor 1.1.3 and Jackson 2.9.8. Am I doing something wrong, or is this an incompatibility with the latest version of Ktor? See this ktor-swagger issue for details: nielsfalk/ktor-swagger#29 Thanks. |
This missing feature is the only thing keeping my company from adopting Ktor. Until then we're using Spring and SpringFox. Huge props to @JLLeitschuh for the work he did. I'd love to see it (or a similar implementation) merged into Ktor itself. I looked around online for a public roadmap but couldn't find one; it'd be nice to at least know if the Ktor/Kotlin/JetBrains team has a plan for this. Even just a "more/less than 6 months" estimate would be great. |
There hasn't been any discussion about this with me or anyone else from the JB team about integrating this. |
Hey :) Thanks for your Effort @JLLeitschuh I just tried your library, and was a little shocked that I needed to use the standard ktor routing functions like |
I'm no longer working for the company that was actually using this library (just moved from working for HPE to working for Gradle). As such, this is no longer the biggest priority for me anymore unfortunately. I'm happy to help anyone else out who wants to add this support to Ktor. As for feature development, I can no longer offer anything more than PR review support and feedback at this point. Sorry. |
Any updates on this? This is really good, it belongs in the official repo! @cy6erGn0m @orangy |
I agree it would be great to hear at least something official back given that this has nearly 80 thumbs-up. |
yes, exactly. please at least let us know if this will be added or not. that will be very helpful. |
any update on this? |
Any updates on this one yet? |
I'm using this variant: https://github.com/papsign/Ktor-OpenAPI-Generator. It's pretty handy but requires testing and discussions with the author. Please join! |
This issue has been automatically marked as stale because it has not had recent activity. |
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks. |
What is the status of this feature? |
It would be really nice if Ktor could support hosting a Swagger UI that is generated from your
routes
configuration.For example, the following could be used to generate a Swagger UI.
This is the swagger UI generated from the above.
I spent today overhauling @nielsfalk's project ktor-swagger to use the newest version of Ktor and also use Gradle to build the application PR here.
I think this project has quite a bit of potential and could satisfy a need in the community by allowing for a fast way to create documentation for API's written using Ktor.
If the Ktor team would like to adopt this project as a feature, I'm happy to try to make the port from the external project it is today into this repository.
If the interest does not exist to adopt a new feature, I totally understand. The concern that I have with publishing this myself (or with @nielsfalk assistance) is the issue of incompatible breaking changes in Ktor (as Ktor is pre-1.0).
I open the floor to the developers of this project. I'd love to see this integrated as a fully supported feature, but I understand if this is outside the scope of this project.
The text was updated successfully, but these errors were encountered: