Flask Python- Swagger for rest apis
We build a simple flask api with get and post methods based api requests.
Link for the code present at end of the blog.
from crypt import methods
from flask import Flask,jsonify,request
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({
"Message": "app up and running successfully"
})
@app.route("/access",methods=["POST"])
def access():
data = request.get_json()
name = data.get("name", "dipto")
server = data.get("server","server1")
message = f"User {name} received access to server {server}"
return jsonify({
"Message": message
})
if __name__=="__main__":
app.run(debug=True,host="0.0.0.0",port=8080)
The api runs at port 8080 , run the api using the command python3 app.py.
The endpoints present are
- / -> returns simple response no parameters
- /access -> returns custom message expects a name and server
Send curl requests to verify api working
- Get Request
curl http://localhost:8080/
- POST Request
curl -X POST -H "Content-Type: application/json" \
-d '{"name": "ezio", "server": "dchost"}' \
http://localhost:8080/access
To use swagger with the api we require the flask_swagger_ui package
pip3 install flask_swagger_ui
Once installed add this section to the flask code
from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL="/swagger"
API_URL="/static/swagger.json"
swagger_ui_blueprint = get_swaggerui_blueprint(
SWAGGER_URL,
API_URL,
config={
'app_name': 'Access API'
}
)
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
We mention the endpoint we want swagger docs to be visible using SWAGGER_URL variable , in this case it be /swagger
We mention the json file which contains the endpoints definition for the api under API_URL
Finally the get_swaggerui_blueprint is used to create a config for the swagger endpoint and it is registered within the app using the register_blueprint method.
Building the swagger docs definition file
Create a directory static and create a file swagger.json.
(Complete json file is present at the end if you want to skip to that part)
Add the initial part for the swagger file which is added at the starting of a swagger file.
{
"swagger": "2.0",
"info": {
"title": "Access API",
"version": "1.0.0"
},
Now we go ahead and add the paths , the first path is the get request which is at ‘/’ endpoint.
- It does not take any parameters from request
- It returns a single response a json
Paths/endpoints are added under the paths key in the json
The simple get request will look like this
"paths": {
"/": {
"get": {
"description": "Returns message showing app is up",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Successful operation"
}
}
}
},
We mention what will be endpoint -> ‘/’
The method is mentioned first under which all other information is provided which includes
- description for the endpoint
- produces: what is response from the endpoint
- responses: the expected responses
Run the app and head to port 8080/swagger to view the swagger endpoints
Send the request using the ‘try it out’ and execute button
Let us now get into the post request which is complicated reliatively
Since we parse the data from json for the post request we need to add two components
- paths: similar to get request this will contain all the information about the endpoint
- definitions: this contains the type of schema to be expected for json requests
The definitions will be defined like this
"definitions": {
"AccessData": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"server": {
"type": "string"
}
}
}
}
As the api expects the user to provide values for ‘name’ and ‘server’ in its payload we define the parameters under properties.
The ‘AccessData’ is the name of the schema , we can have multiple schemas under definitions if we require different variations of payloads in different endpoints.
This schema will be mapped to the endpoints path so swagger is aware of what to expect.
"/access": {
"post": {
"description": "Grants access to an user",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "access data",
"in": "body",
"description": "JSON data for the api",
"required": true,
"schema": {
"$ref": "#/definitions/AccessData"
}
}
],
"responses": {
"200": {
"description": "User granted access"
},
"400": {
"description": "Invalid request data"
}
}
}
}
We define the endpoint under which we define the type of request
- produces: the type of response to expect
- consumes: the type of request that it will accept
- parameters: the data about the endpoint , the schema defined above is mapped here so swagger is aware what type of requests to pickup and what type of requests to deny
- responses : based on the type of data provided either return 200 or 400
Running the app again and heading to /swagger endpoint
Execute the api using custom data
Complete Swagger doc
{
"swagger": "2.0",
"info": {
"title": "Access API",
"version": "1.0.0"
},
"paths": {
"/": {
"get": {
"description": "Returns message showing app is up",
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "Successful operation"
}
}
}
},
"/access": {
"post": {
"description": "Grants access to an user",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "access data",
"in": "body",
"description": "JSON data for the api",
"required": true,
"schema": {
"$ref": "#/definitions/AccessData"
}
}
],
"responses": {
"200": {
"description": "User granted access"
},
"400": {
"description": "Invalid request data"
}
}
}
}
},
"definitions": {
"AccessData": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"server": {
"type": "string"
}
}
}
}
}
Code can be found here -> Link to github repository.