REST channels

REST channels offer several interesting points that facilitate the development of APIs based on JSON.

  • URL paths can include patterns
  • URL parameters can form part of the input to a service
  • Users can decide which parameter types take precedence over one another
  • Access to a channel can be limited to a selected HTTP verb only
  • Data format can be set to JSON, XML or none in particular at all
  • Services can react to user-chosen HTTP verbs only (documented in a separate chapter)
  • Role-Based Access Control can be used to assign roles and actions to clients applications and HTTP verbs they are allowed to use

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'

Clean URLs with path patterns

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:

INFO - Customer: 37172
INFO - Account: HAZDM017

Parameters in query path

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:

INFO - Customer: 198271
INFO - Account: KMZQ62M

Using JSON payload

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"}}
$
INFO - Customer: 38631
INFO - Account: JZM92KH

Parameters priority

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.

HTTP methods

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.

Data format

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.