New REST programming examples
As we are preparing to release Zato 3.2 soon, all the programming examples are being rewritten to showcase what the platform is capable of. That includes REST examples too and this article presents a few samples taken from the documentation.
For fuller discussion and more examples - check the documentation.
Calling REST APIs
-
All data can be prepared as dict objects - this includes the payload, query string parameters, path parameters and HTTP headers too
-
Zato will fill in patterns in URL paths, e.g. if the path is
/api/billing/{phone_no}
then the code below will substitute 271637517 for phone_no and the rest of the parameters will go the query string
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class SetBillingInfo(Service):
""" Updates billing information for customer.
"""
def handle(self):
# Python dict representing the payload we want to send across
payload = {'billing':'395.7', 'currency':'EUR'}
# Python dict with all the query parameters, including path and query string
params = {'cust_id':'39175', 'phone_no':'271637517', 'priority':'normal'}
# Headers the endpoint expects
headers = {'X-App-Name': 'Zato', 'X-Environment':'Production'}
# Obtains a connection object
conn = self.out.rest['Billing'].conn
# Invoke the resource providing all the information on input
response = conn.post(self.cid, payload, params, headers=headers)
# The response is auto-deserialised for us to a Python dict
json_dict = response.data
# Assign the returned dict to our response - Zato will serialise it to JSON
# and our caller will get a JSON message from us.
self.response.payload = json_dict
Accepting REST calls
- Use
self.request.payload
to access input data - it is a dict object created by Zato out of the parsed JSON request
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class LogInputData(Service):
""" Logs input data.
"""
def handle(self):
# Read input received
user_id = self.request.payload['user_id']
user_name = self.request.payload['user_name']
# Store input in logs
self.logger.info('uid:%s; username:%s', user_id, user_name)
Reacting to REST verbs
-
Implement
handle_<VERB>
to react to specific HTTP verbs when accepting requests -
If the service is invoked with a verb that it does not implement, the API client receives status
405 Method Not Allowed
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class MultiVerb(Service):
""" Logs input data.
"""
def handle_GET(self):
self.logger.info('I was invoked via GET')
def handle_POST(self):
self.logger.info('I was invoked via POST')
Request and response objects
- All data and metadata is available via
self.request
andself.response
attributes. Security-related details are inself.channel.security
.
Request object:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class RequestObject(Service):
def handle(self):
# Here is all input data parsed to a Python object
self.request.payload
# Here is input data before parsing, as a string
self.request.raw_request
# Correlation ID - a unique ID assigned to this request
self.request.cid
# A dictionary of GET parameters
self.request.http.GET
# A dictionary of POST parameters
self.request.http.POST
# REST method we are invoked with, e.g. GET, POST, PATCH etc.
self.request.http.method
# URL path the service was invoked through
self.request.http.path
# Query string and path parameters
self.request.http.params
# This is a method, not an attribute,
# it will return form data in case we were invoked with one on input.
form_data = self.request.http.get_form_data()
# Username used to invoke the service, if any
self.channel.security.username
# A convenience method returning security-related details
# pertaining to this request.
sec_info = self.channel.security.to_dict()
Response object:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class ResponseObject(Service):
# Returning responses as a dict will make Zato serialise it to JSON
self.response.payload = {'user_id': '123', 'user_name': 'my.user'}
# String data can also be always be returned too,
# e.g. because you already have data serialised to JSON or to another data format
self.response.payload = '{"my":"response"}'
# Sets HTTP status code
self.response.status_code = 200
# Sets HTTP Content-Encoding header
self.response.content_encoding = 'gzip'
# Sets HTTP Content-Type - note that Zato itself
# sets it for JSON, you do not need to do it.
self.response.content_type = 'text/xml; charset=UTF-8'
# A dictionary of arbitrary HTTP headers to return
self.response.headers = {
'Strict-Transport-Security': 'Strict-Transport-Security: max-age=16070400',
'X-Powered-By': 'My-API-Server',
'X-My-Header': 'My-Value',
}
Next steps
-
Start the tutorial to learn more technical details about Zato, including its architecture, installation and usage. After completing it, you will have a multi-protocol service representing a sample scenario often seen in banking systems with several applications cooperating to provide a single and consistent API to its callers.
-
Visit the support page if you would like to discuss anything about Zato with its creators
-
Para aprender más sobre las integraciones de Zato y API en español, haga clic aquí