Blog
REST channels offer several interesting points that facilitate the development of APIs based on JSON.
Note that in order to take advantage of URL path patterns and URL parameters a service needs to use SimpleIO. This is what the service below uses.
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetBalance(Service):
class SimpleIO:
input_required = 'cust_no', 'account_no'
output_required = 'balance', 'currency'
def handle(self):
# Confirm input was received
self.logger.info('Customer: %s', self.request.input.cust_no)
self.logger.info('Account: %s', self.request.input.account_no)
# Produce sample output
self.response.payload.balance = '357.19'
self.response.payload.currency = 'EUR'
A sample clean URL may read http://localhost:11223/customer/balance/37172/HAZDM017/ and to configure it from the web admin one would fill out a form to create a REST as follows. Note that the URL path contains parameters enclosed between {
and }
.
Now the service can be invoked using a nice and clean URL:
$ curl http://localhost:11223/customer/balance/37172/HAZDM017/ ; echo
{"response": {"currency": "EUR", "balance": "357.19"}}
$
And the contents of server.log confirms that the input was received fine:
The same service can be mounted on another channel that will let client applications use query parameters rather than ones embedded in a path.
$ curl "http://localhost:11223/customer/balance?cust_no=198271&account_no=KMZQ62M" ; echo
{"response": {"currency": "EUR", "balance": "357.19"}}
$
Again, server.log confirms the input was the same:
Note that it is always possible to invoke the very same service by using JSON payload on input:
$ curl http://localhost:11223/customer/balance -d \
'{"cust_no":"38631", "account_no":"JZM92KH"}' ; echo
{"response": {"currency": "EUR", "balance": "357.19"}}
$
Given that there are 3 sources of parameters - payload, URL path and the query string - a two-fold priority resolution mechanism lets one decide which ones take precedence over another if it happens that the same parameter is provided more than once on input.
"URL params priority" can be one QS over path
or Path over QS
. If it is "QS over path" then query string parameters are prefered over parameters found using path parameters. With "Path over QS" it is the other way around.
Once it is decided if either query string or path parameters have priority, their precedence over payload gets decided.
"Params priority" can be URL over message
or Message over URL
. With "URL over message", parameters resulting from the previous decision take precedence over payload in the message. With "Message over URL" it is the other way around.
A channel can be configured to accept an arbitrary HTTP method only. Requests submitted using any other method will be rejected.
A service can restrict the range of methods supported even if a given channel doesn't however once a channel picks the verb to react to the service will not be able to make use of any other.
An HTTP channel can be set to take JSON, XML or HL7 on input. That allows Zato to automatically extract parameters from the incoming message and serialize the response out of the payload a service produces.
It is also possible not to set the data format to any specific one, for instance, if using HL7 v2 the service will parse the message itself.