Blog
One of the exciting additions of the upcoming Zato 3.2 release is the ability to invoke services through OpenAPI endpoints without a need for creation of REST channels explicitly - read more for details.
Supposing we have a service such as below - note that it is uses SimpleIO and that each of its input/output attributes is documented in the docstring - we would like to invoke it from an external application while delegating to Zato as much effort involved in it as possible.
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetUserAccount(Service):
""" Returns user account details based on user ID and type.
"""
name = 'api.get.user.account'
class SimpleIO:
"""
* account_id - ID of the user account to return
* user_type - Type of the user the account belongs to
* user_name - Name of the user to whom account_id belongs
* needs_review - A flag indicating whether the account needs to be reviewed
"""
input_required = 'account_id', 'user_type'
output_required = 'account_name', 'needs_review'
def handle(self):
# Local aliases
account_id = self.request.input.account_id
user_type = self.request.input.user_type
# In reality, additional work would be carried out here first ..
self.logger.info('Returning data for `%s` (%s)', account_id, user_type )
# .. produce the output now.
self.response.payload.user_name = 'my.user'
self.response.payload.needs_review = True
We will not pursue this path in this article but, in other circumstances, we could just create a REST channel for the service. This is great and it works perfectly fine, always letting one adjust many options, such as caching or rate-limiting.
However, today, we will auto-create API definitions using OpenAPI.
Documentation, including OpenAPI specifications, can be created from the command line, as below:
$ zato apispec /path/to/server \
--dir /my/output/directory \
--include api.* \
--tags public \
--verbose
What we will find in the output directory is a Sphinx project with human-readable documentation, which is nice in itself, along with formal specifications, including OpenAPI.
Upon downloading the openapi.yaml file we can confirm that it is a formal specification of the APIs exposed - including request and response schemas as well as endpoint addresses.
Note that, because we are using SimpleIO, the specification includes description of parameters and the parameters have expected data types, e.g. account_id is an integer while needs_review is a boolean.
components:
schemas:
request_api_get_user_account:
properties:
account_id:
description: ID of the user account to return
format: int32
type: integer
user_type:
description: Type of the user the account belongs to
format: string
type: string
required:
- account_id
- user_type
title: Request object for api.get.user.account
type: object
response_api_get_user_account:
properties:
needs_review:
description: A flag indicating whether the account needs to be reviewed
format: boolean
type: boolean
user_name:
description: Name of the user to whom account_id belongs
format: string
type: string
required:
- user_name
- needs_review
title: Response object for api.get.user.account
type: object
paths:
/zato/api/invoke/api.get.user.account:
post:
consumes:
- application/json
operationId: post__zato_api_invoke_api_get_user_account
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/request_api_get_user_account'
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/response_api_get_user_account'
info:
title: API spec
version: '1.0'
openapi: 3.0.2
servers:
- url: http://localhost:11223
With the specification downloaded, we can start to invoke our service immediately - in this case, we will use Postman. Essentially, import a definition, choose the desired service, provide input data and click the "Send" button.
Afterwards, we can also confirm in Zato server logs that the request was processed correctly.
Naturally, Postman is just a sample client utilizing the OpenAPI specification - clients in other languages can be easily used as well, including Python, Java, .NET, JavaScript and more.
The above suffices for external clients to invoke your services purely based on their Python definitions with endpoints, documentation and specifications auto-generated by Zato.
But there is more. Have you noticed that nothing in the service used is specific to REST, OpenAPI or HTTP for that matter?
That is one of the benefits of using Zato - such a service is completely reusable across a range of other protocols, which means that it can exposed as-is through other channels, e.g. IBM MQ, AMQP, SOAP, WebSockets, Publish/Subscribe topics, Scheduler, File transfer and many more.
Be sure to check [the Zato documentation]/en/docs/3.2/index.html for more details!