common.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package openapi
  14. import (
  15. "github.com/emicklei/go-restful"
  16. "github.com/go-openapi/spec"
  17. "strings"
  18. )
  19. // OpenAPIDefinition describes single type. Normally these definitions are auto-generated using gen-openapi.
  20. type OpenAPIDefinition struct {
  21. Schema spec.Schema
  22. Dependencies []string
  23. }
  24. type ReferenceCallback func(path string) spec.Ref
  25. // OpenAPIDefinitions is collection of all definitions.
  26. type GetOpenAPIDefinitions func(ReferenceCallback) map[string]OpenAPIDefinition
  27. // OpenAPIDefinitionGetter gets openAPI definitions for a given type. If a type implements this interface,
  28. // the definition returned by it will be used, otherwise the auto-generated definitions will be used. See
  29. // GetOpenAPITypeFormat for more information about trade-offs of using this interface or GetOpenAPITypeFormat method when
  30. // possible.
  31. type OpenAPIDefinitionGetter interface {
  32. OpenAPIDefinition() *OpenAPIDefinition
  33. }
  34. // Config is set of configuration for openAPI spec generation.
  35. type Config struct {
  36. // List of supported protocols such as https, http, etc.
  37. ProtocolList []string
  38. // Info is general information about the API.
  39. Info *spec.Info
  40. // DefaultResponse will be used if an operation does not have any responses listed. It
  41. // will show up as ... "responses" : {"default" : $DefaultResponse} in the spec.
  42. DefaultResponse *spec.Response
  43. // CommonResponses will be added as a response to all operation specs. This is a good place to add common
  44. // responses such as authorization failed.
  45. CommonResponses map[int]spec.Response
  46. // List of webservice's path prefixes to ignore
  47. IgnorePrefixes []string
  48. // OpenAPIDefinitions should provide definition for all models used by routes. Failure to provide this map
  49. // or any of the models will result in spec generation failure.
  50. GetDefinitions GetOpenAPIDefinitions
  51. // GetOperationIDAndTags returns operation id and tags for a restful route. It is an optional function to customize operation IDs.
  52. GetOperationIDAndTags func(servePath string, r *restful.Route) (string, []string, error)
  53. // GetDefinitionName returns a friendly name for a definition base on the serving path. parameter `name` is the full name of the definition.
  54. // It is an optional function to customize model names.
  55. GetDefinitionName func(servePath string, name string) (string, spec.Extensions)
  56. // PostProcessSpec runs after the spec is ready to serve. It allows a final modification to the spec before serving.
  57. PostProcessSpec func(*spec.Swagger) (*spec.Swagger, error)
  58. // SecurityDefinitions is list of all security definitions for OpenAPI service. If this is not nil, the user of config
  59. // is responsible to provide DefaultSecurity and (maybe) add unauthorized response to CommonResponses.
  60. SecurityDefinitions *spec.SecurityDefinitions
  61. // DefaultSecurity for all operations. This will pass as spec.SwaggerProps.Security to OpenAPI.
  62. // For most cases, this will be list of acceptable definitions in SecurityDefinitions.
  63. DefaultSecurity []map[string][]string
  64. }
  65. // This function is a reference for converting go (or any custom type) to a simple open API type,format pair. There are
  66. // two ways to customize spec for a type. If you add it here, a type will be converted to a simple type and the type
  67. // comment (the comment that is added before type definition) will be lost. The spec will still have the property
  68. // comment. The second way is to implement OpenAPIDefinitionGetter interface. That function can customize the spec (so
  69. // the spec does not need to be simple type,format) or can even return a simple type,format (e.g. IntOrString). For simple
  70. // type formats, the benefit of adding OpenAPIDefinitionGetter interface is to keep both type and property documentation.
  71. // Example:
  72. // type Sample struct {
  73. // ...
  74. // // port of the server
  75. // port IntOrString
  76. // ...
  77. // }
  78. // // IntOrString documentation...
  79. // type IntOrString { ... }
  80. //
  81. // Adding IntOrString to this function:
  82. // "port" : {
  83. // format: "string",
  84. // type: "int-or-string",
  85. // Description: "port of the server"
  86. // }
  87. //
  88. // Implement OpenAPIDefinitionGetter for IntOrString:
  89. //
  90. // "port" : {
  91. // $Ref: "#/definitions/IntOrString"
  92. // Description: "port of the server"
  93. // }
  94. // ...
  95. // definitions:
  96. // {
  97. // "IntOrString": {
  98. // format: "string",
  99. // type: "int-or-string",
  100. // Description: "IntOrString documentation..." // new
  101. // }
  102. // }
  103. //
  104. func GetOpenAPITypeFormat(typeName string) (string, string) {
  105. schemaTypeFormatMap := map[string][]string{
  106. "uint": {"integer", "int32"},
  107. "uint8": {"integer", "byte"},
  108. "uint16": {"integer", "int32"},
  109. "uint32": {"integer", "int64"},
  110. "uint64": {"integer", "int64"},
  111. "int": {"integer", "int32"},
  112. "int8": {"integer", "byte"},
  113. "int16": {"integer", "int32"},
  114. "int32": {"integer", "int32"},
  115. "int64": {"integer", "int64"},
  116. "byte": {"integer", "byte"},
  117. "float64": {"number", "double"},
  118. "float32": {"number", "float"},
  119. "bool": {"boolean", ""},
  120. "time.Time": {"string", "date-time"},
  121. "string": {"string", ""},
  122. "integer": {"integer", ""},
  123. "number": {"number", ""},
  124. "boolean": {"boolean", ""},
  125. "[]byte": {"string", "byte"}, // base64 encoded characters
  126. }
  127. mapped, ok := schemaTypeFormatMap[typeName]
  128. if !ok {
  129. return "", ""
  130. }
  131. return mapped[0], mapped[1]
  132. }
  133. func EscapeJsonPointer(p string) string {
  134. // Escaping reference name using rfc6901
  135. p = strings.Replace(p, "~", "~0", -1)
  136. p = strings.Replace(p, "/", "~1", -1)
  137. return p
  138. }