HTTP Method and Accept Headers

Zato 3.1 includes new means to manage access to REST services based on input Method and Accept headers in HTTP requests — here is how they can be employed in practice.


Prior to Zato 3.1, you could always build a REST API reacting to individual HTTP verbs by implementing handle_VERB methods in services, such as:

class MyService(Service):

    def handle_GET(self):
        # Reacts to GET requests

    def handle_POST(self):
        # Reacts to POST requests

    # Any other handle_VERB method will be used accordingly

This works and will continue to work as expected in all future Zato versions.

However, if you use SimpleIO, and keep all handler methods in the same service, all of them share the same SIO definition; this is not always desirable — for instance, input to POST may be unrelated to input that DELETE receives.

REST Channel URL Paths

In Zato 3.1, it is possible to create REST channels that have the same URL path but different services mounted on each channel. This can be done separately for each HTTP verb required.

Previously it was a single service with multiple handle_VERB methods. Now, it can be a set of services, each reacting to a different HTTP verb, with all of them mounted on the same URL path.

In a way, this was supported previously but, if handle_VERB methods were not used, URL paths had to be distinct, e.g.

GET /api/user
DELETE /api/user/delete
POST /api/user/create

In 3.1+, this can be simplified to:

GET /api/user
DELETE /api/user
POST /api/user

Now, each of the combination of verb + path may be unique for a REST channel while previously each channel needed to have its own URL path.

Moreover, because each channel may have its own separate service, it also means that each service may have its own SimpleIO definition; the service then becomes less tied to REST.

HTTP Accept Headers

This is a completely new feature in 3.1, which lets you have distinct REST channels, depending on the requests' Accept headers.

For instance, let's say that we would like to process incoming invoices under POST /api/invoice, but we would like to have two services reacting to the same endpoint, one for JSON and now for PDF invoices.

This can be achieved by configuring HTTP Accept headers in their channels, as below — note that the method and URL paths are the same in both cases, yet HTTP Accept and services are different because each service reacts to a different value of HTTP Accept:

Process JSON invoice

Process JSON invoice

Process PDF invoice

Process PDF invoice

HTTP Accept Header Patterns

We can do one better and take advantage of Accept header patterns — with an asterisk meaning any character. This will configure the channel to process requests matching any value that fits in with the pattern. (E.g. text/* will mean text/csv, text/xml or anything that starts with text/.)

Processing requesting matching the given pattern

Processing request, matching the given pattern

However, seeing as it can be a number of input MIME types, at this point we may need to know what the actual value was — this can be extracted from the WSGI environment via self.wsgi_environ.


Zato 3.1 saw improvements and backward-compatible changes to how REST channels can be built.

It will now support more use-cases, such as single URL path channels with different HTTP verbs and independent SimpleIO definitions or HTTP Accept headers different for each channel.

In turn, this lets one build REST APIs that are more flexible and elastic in their design to react to different input criteria.