Hello everyone we are running a Falcon application that uses the falcon-apispec library to generate OpenAPI specifications.
Here is our code that initializes the definition:
import falcon
from apispec import APISpec
from falcon_apispec import FalconPlugin
from kubernetes import config
from api.admission_response import AdmissionResponse
from api.health import Health
from api.k8s_config_validator import K8sConfigValidator
from api.middleware.json import RequireJSON, JSONTranslator
from api.apidocs import ApiDocs
def create_app(config_validator):
api = falcon.API(middleware=[
RequireJSON(),
JSONTranslator(),
])
resources ={
'/': AdmissionResponse(config_validator),
'/api-docs': ApiDocs(),
'/health': Health()
}
for r in resources:
api.add_route(r, resources[r])
setup_swagger_documentation(api, resources)
# initialize k8s client
config.load_incluster_config()
return api
def get_app():
return create_app(K8sConfigValidator())
def setup_swagger_documentation(api, resources):
spec = APISpec(
title='Admission Controller API',
version='latest',
openapi_version='2.0',
plugins=[
FalconPlugin(api)
],
info=dict(description="Admission Controller API"),
)
for r in resources:
spec.path(resource=resources[r])
with open('./api/config/openapi/openapi_spec.yaml', 'w') as f:
f.write(spec.to_yaml())
Here is our openapi-spec defintion defined:
openapi: 3.0.0
info:
description: Admission Controller API
title: Admission Controller API
version: latest
paths:
/:
post:
tags:
- "API"
parameters:
- in: "query"
name: "body"
description: "List of user object"
required: true
schema:
type: string
responses:
"200":
description: "Success"
/api-docs:
get:
tags:
- "API Doc Endpoints"
responses:
"200":
description: "Success"
/health:
get:
tags:
- "Health Endpoints"
responses:
"200":
description: "Success"
And here is one of the classes that defines what should be done on a post:
class AdmissionResponse(object):
def __init__(self, k8s_config_validator):
self.k8s_config_validator = k8s_config_validator
#falcon.before(validate_schema)
def on_post(self, req, resp):
"""
---
tags: ['API']
parameters:
- in: "query"
name: "body"
description: "List of user object"
required: true
type: string
responses:
"200":
description: "Success"
"""
admission_review = AdmissionReview(req.context['doc'])
errors = self.k8s_config_validator.validate(admission_review)
if errors:
resp.context['result'] = ResponseBuilder(admission_review).not_allowed(errors)
api.logger.info("Validations for %s of kind %s in %s failed with %s", admission_review.name(), admission_review.kind(), admission_review.namespace(), errors)
else:
resp.context['result'] = ResponseBuilder(admission_review).allowed()
api.logger.info("Validations for %s of kind %s in %s passed", admission_review.name(), admission_review.kind(), admission_review.namespace())
Whenever we try to hit our hosted swagger-ui we run into this error:
Unable to render this definition The provided definition does not specify a valid version field.
Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
Does anyone know how we could resolve this? When we paste in our openapi specification to the swagger editor located here: https://editor.swagger.io/ it works just fine. Any help would be awesome!
When calling APISpec, not all strings are supported.
Try something like "0.0.1" (you supplied 'latest').
Also, using falcon_swagger_ui, an error may be reported if the openapi_version format is not correct (in such case, examples of valid formats are provided).
This works for me:
spec = APISpec(
title="My APP",
version="0.0.1",
openapi_version='3.0.0',
plugins=[FalconPlugin(api)]
)
Related
I'm trying to write a yaml that will generate a nodejs stub-server serving a file. Swagger codegen generates server that replies nothing.
swagger: "2.0"
info:
description: ""
version: "1"
title: "Swagger example"
host: "localhost:3200"
basePath: "/v2"
schemes:
- "http"
paths:
/getImage:
get:
tags:
- "image"
summary: "Returns image"
description: ""
operationId: "getImage"
produces:
- "application/octet-stream"
responses:
"200":
description: "successful operation"
schema:
type: "file"
example:
sampleFile:
summary: "A sample file"
externalValue: "http://github.com/topheroes/topheroes.github.io/raw/master/img/dragon.png"
"400":
description: "Invalid value"
Is there a way to generate a stub that will serve a local or a random binary (image) file?
I tried type: string and format: binary, I tried url in example. Nothing seems to work.
Please advice
I'm setting up a new server and my goal is to implement multipart/form-data in OpenApi3.0's yaml file. I encounter "should NOT have additional properties (consume)" error in Node.js and wanna know how to fix this error or how to implement multipart/form-data in OpenApi3.0's yaml file?
This is my OpenApi3.0's yaml file to implement this goal, it will report the error I mentioned above.
openapi: 3.0.1
info:
title: myapp
description: My cool app
version: 1.0.0
servers:
- url: /api/v1/user
tags:
- name: User
description: User Operations
paths:
/onboarding/signature:
post:
tags:
- User
description: Onboarding Upload Signature API - with parameters user's email and image file
requestBody:
description: Request Body {email, image}
content:
multipart/form-data:
schema:
$ref: '#/components/schemas/onboardingSignature'
required: true
responses:
200:
description: OK
201:
description: Created
400:
description: Bad Request
500:
description: Internal Server Error
components:
schemas:
onboardingSignature:
description: Onboarding Signature File
type: object
properties:
email:
type: string
image:
format: binary
I expect the implementation of uploading file in Swagger use multipart/form-data format.
I have an issue with the embedded API management within a Cloud Foundry application ( node.js ) on bluemix .There is a certain path in the yaml which is not working via the gateway, please see below the relevant path from the yaml:
/socket.io/:
get:
produces:
- text/plain; charset=utf-8
parameters: []
responses:
default:
description: Definition generated from Swagger Inspector
I get 404 , not found.
The url works fine when I dont go via the gateway.
The url is https://[masked api mgd hostname]/socket.io/?EIO=3&transport=polling&t=MC0pE73
Please help.
Find attached the complete yaml below
swagger: "2.0"
info:
description: defaultDescription
version: "0.1"
title: defaultTitle
host: masked.actualEndpoint
schemes:
- https
basePath: "/"
paths:
/socket.io/:
get:
parameters:
- name: t
in: query
required: false
type: string
x-example: MC0pE73
- name: EIO
in: query
required: false
type: string
x-example: "3"
- name: transport
in: query
required: false
type: string
x-example: polling
responses:
default:
description: Definition generated from Swagger Inspector
definitions: {}
am accessing the url using https://[ masked api mangd hostname ]/socket.io/?EIO=3&transport=polling&t=MCvtHJT
I believe its the / at the end of the path ( /socket.io/ ) which is causing the gateway to fail. Any comments.
I'm trying to define a post endpoint using swagger, but it isn't allowing the requestBody parameter:
/names/{roster}:
get:
#...
post:
x-swagger-router-controller: names
description: Adds or removes name(s)
operationId: manageNames
parameters:
- name: roster
in: path
description: the roster to use
type: string
required: true
requestBody:
content:
'application/json':
schema:
$ref: '#/definitions/ManageNamesRequest'
when I run npm start, I get this:
API Errors:
#/paths/~1names~1{roster}/post: Additional properties not allowed: requestBody
1 error and 0 warnings
What's wrong with my spec?
You are probably mixing OpenAPI/Swagger 2.0 and OpenAPI 3.0 syntax. Your spec seems to be 2.0, but the requestBody keyword is a 3.0 feature. In 2.0, the request body is defined as a body parameter:
paths:
/names/{roster}:
post:
produces:
- application/json
...
parameters:
- ...
- in: body
name: body
required: true
schema:
$ref: '#/definitions/ManageNamesRequest'
More info: Describing Request Body
I'm using Swagger with NodeJS, and when I test an example I have this error.
Here is my YAML:
swagger: "2.0"
info:
version: "0.0.1"
title: Hello World App
# during dev, should point to your local machine
host: localhost:10010
# basePath prefixes all resource paths
basePath: /
#
schemes:
# tip: remove http to make production-grade
- http
- https
# format of bodies a client can send (Content-Type)
consumes:
- application/json
# format of the responses to the client (Accepts)
produces:
- application/json
paths:
/movie:
# our controller name
x-swagger-router-controller: movie
get:
description: get the movies list
# define the type of response for Success "200" and Error
responses:
"200":
description: Success
schema:
$ref: "#/definitions/GetMoviesListResponse"
default:
description: Error
schema:
$ref: "#/definitions/ErrorResponse"
/swagger:
x-swagger-pipe: swagger_raw
# complex objects have schema definitions
definitions:
GetMoviesListResponse:
required:
- movies
properties:
# The array of movies
movies:
type: array
items:
type: object
properties:
id:
type: string
title:
type: string
year:
type: number
ErrorResponse:
required:
- message
properties:
message:
type: string
Given your YAML, and assuming you're using swagger-tools with the options given in their tutorials, x-swagger-router-controller: movie will route any requests to GET /movie to a function called get exported from the module /controllers/movie.js in your project. Have you set that up?
Also check your swagger options to check that the correct controllers path is included, e.g. controllers: `${__dirname}`/controllers.