DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Breaking Up a Monolithic Database with Kong
  • User-Friendly API Publishing and Testing With Retrofit
  • Building a Secure REST API with OpenID Connect
  • Building REST API Backend Easily With Ballerina Language

Trending

  • Analyzing “java.lang.OutOfMemoryError: Failed to create a thread” Error
  • How to Convert Between PDF and TIFF in Java
  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  • Key Considerations in Cross-Model Migration
  1. DZone
  2. Data Engineering
  3. Databases
  4. Diving Deep Into REST API Channels

Diving Deep Into REST API Channels

This article provides a deep dive into how developers can work with REST API services, cache, message logs, and more by using a single platform.

By 
Dariusz Suchojad user avatar
Dariusz Suchojad
·
Jan. 06, 21 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
9.6K Views

Join the DZone community and get the full member experience.

Join For Free

Let's begin in 2021 with a deep dive into Zato REST API channels. What are they? How can we use them efficiently? How can they be configured for maximum flexibility? Read on to learn all the details.

A Sample Service

First, let's have a look at a sample service that we want to make available to API clients.

Python
 




x
28


 
1
# -*- coding: utf-8 -*-
2

          
3
# Zato
4
from zato.server.service import Service
5

          
6
class GetUserDetails(Service):    
7
    """ Returns details of a selected user.    
8
    """    
9
    name = 'api.user.get-details'
10

          
11
    class SimpleIO:        
12
        input_required = 'user_name'        
13
        output_required = 'email', 'user_type'
14

          
15
    def handle(self): 
16

          
17
        # Log what we are about to do.
18
        self.logger.info('Returning details of `%s`', self.request.input.user_name)
19

          
20
        # In real code, we would look up the details in a database,
21
        # but not necessarily in a cache - read the article why it is not needed.
22
        details = {
23
            'email': 'my.user@example.com',            
24
            'user_type': 'ABC'        
25
       }
26

          
27
        # Return the response now.
28
        self.response.payload = details
6
class GetUserDetails(Service):    



The first thing that may strike you is that the code is very high level – it just has access to a user_name and some data is returned but there is no mention of REST, no data serialization, caching, or anything that is not involved in the business functionality of returning user details.

This is by design. In Zato, services focus on what they actually need to do and the lower-level details are left to the platform. In other words, the service does not need to be concerned with the peculiarities of a given transport method, it just has its input to process and output to produce – it is channeled in front of a service that deals with all such aspects and the service concentrates on higher-level logic.

This makes it possible to employ the same service in other contexts – for instance, we are describing REST channels today, but the very same service could be invoked from the scheduler, through AMQP, IBM MQ, or via other channels, including multiple REST channels, helping you to design a reusable Service-Oriented Architecture (SOA).

With that in mind, let's move on to REST channels.

REST API Channels

In the Zato web-admin, a definition of a sample REST channel making use of our service may look like the below screenshots:

Zato web-admin channels menu screenshot.

Creating a REST channel in Zato web-admin screenshot.

Now that we have created a new channel, we can invoke it to confirm that it works as expected.

Shell
 




xxxxxxxxxx
1


 
1
% curl localhost:17010/api/v1/user/my.username ; echo
2
{"email": "my.user@example.com", "user_type": "ABC"}
3
%



We should see the following message in the server logs:

Plain Text
 




xxxxxxxxxx
1


 
1
INFO - api.user.get-details - Returning details of `my.username`



Great! Everything is fine and we can proceed.

Just one note about channels: remember that there can be many channels pointing to the same service. This lets you reuse the services in various scenarios, e.g. you can have a separate REST channel with its own security definition for each external application connecting to your APIs.

Whenever you add, modify or delete a channel, the service as such is unchanged, including any other channels. Conversely, when you update service, for instance adding new functionality, all channels using it will automatically invoke the new version of the service.

Channels come with good defaults when you create them, but it is always possible to customize them to one's particular needs. Let's go step-by-step through each attribute of a channel's definition.

Basic Information

  • Name: Each channel has a unique name which can be arbitrary, depending on your naming conventions.
  • Active: An inactive channel cannot be invoked; doing so will yield a 404 error.

URL Path and Query String

  • URL path: URL paths need to be unique. Each path can contain one or more patterns to match input parameters. This is why in our service we were able to reference self.request.input.user_name – it was extracted from the URL path.
  • Match slash: Sometimes, URL path parameters sent from API clients will contain the slash character which normally is used to separate path components. This checkbox controls whether the path patterns should match a slash or not.
  • URL params: QS over path vs. Path over QS. Usually, applications will send parameters in one place only, e.g. only in the URL path or in query string parameters. But what if an application has good reasons to send parameters in both the query string and URL path, for instance /api/v1/user/my.username?user_name=my.other.username – this happens from time to time and this setting lets you control which of the two will take precedence.
  • Merge to request: This is used if parameters are sent via a query string in addition to the URL path. If checked, such query string parameters will be accessible through self.request.input, otherwise, they will exist only in self.request.http.GET.
  • Params priority: This is similar to the options above but it will control the behavior if parameters are sent in both the JSON message body as well as in the URL path or query string – it lets one decide which will have higher priority and which will become available in self.request.input.

HTTP Metadata and Data Format

  • Method - it is possible to specify that only specific HTTP methods can be used to invoke the channel. This is not always needed. For instance, the service above can work just fine with either GET or POST, depending on what the caller prefers. Conceptually, this is a GET request, but some API clients will always use POST, which is why filling out this field is not always needed or advised.
    A service can handle multiple methods, either as a whole or a channel, and can dispatch requests to specific parts of the service depending on which method is used, i.e. you can add handle_GET, handle_POST, and other such methods independently, resulting, for instance, in a user service that handles CRUD via respective handle_* methods.
  • Encoding: Can be set to "gzip" to enable compression of responses from the channel.
  • Data format: Can code in JSON, XML, or HL7 to enable auto de-serialization of requests and responses. Note that the original request, prior to any processing, is always available in self.request.raw_request.
  • Accept header: Decides to which Accept HTTP headers the channel should react. Note that, just like with methods, it is possible for the service to handle each header separately, which lets one have the same service produce different responses depending on what the client's Accept header dictates.

API Service and Security

  • Service: The service that is mounted on this channel will be given incoming requests on input, as in the code example above. The same service may be mounted on multiple channels.
  • Security definition: Determine the kind of authentication mechanism this channel requires. This can be basic auth, an API key, JWT, Vault, WS-Security, or XPath. Each channel may have a different security definition assigned and the same definition can be assigned to multiple channels. Note that, to avoid any misunderstandings, you need to explicitly choose "No security definition" if the channel should not handle authentication itself, perhaps because the service should do it on its own, i.e. it is not possible to forget to choose something here and leave a channel unsecured by mistake.
  • RBAC: A channel can also use Role-Based Access Control definitions, where each API client is assigned fine-grained permissions to individual methods and roles, possibly hierarchical ones, which control if a particular client can invoke the channel's service. For instance, some API clients may be allowed to only read (GET) data whereas different ones will be able to create, update, and delete it too (POST, PATCH and DELETE).

Cache

  • Cache type: Optionally, this can be set to be either built-in or Memcached. Requests matching previous ones will be automatically served from a specific cache assigned to the channel. With the built-in cache, the response is served from RAM directly, resulting in very fast responses. It is possible to browse, modify, or delete the cached data, as shown below:

Zato web-admin built-in cache list screenshot.

Zato web-admin built-in cache entry details screenshot.

Rate Limiting

The rate-limiting stanza was not expanded upon previously, so let's do it now to add a rate-limiting the definition to our channel. As usual, the limits can be set separately for each channel.

Zato web-admin channel's rate limiting definition screenshot.

In this particular case, clients connecting from the internal network will be allowed to issue 30 requests per minute but connections from localhost can invoke it 50k times an hour. And everyone else is limited to 100 requests a day.

Message Log

Just like with rate limiting, these options were not expanded upon in the initial screenshot so here they are. Each channel can keep N's last messages received, sent, or both. It is also possible to say that only the first X kilobytes of a given message is to be stored – some messages may be too large for it to be practical to keep them in their entirety. When the log becomes full, the oldest messages are discarded, making room for newer ones.

Zato web-admin channel's message log definition screenshot.

Stored messages can be browsed in the web admin console, immediately letting one know what a given channel receives and sends.

Zato web-admin channel's message log definition screenshot.

Such a message log is a feature common to other elements of Zato, e.g. HL7 or WebSocket connections have their own message logs too.

Documentation and OpenAPI (WSDL Too)

It is good that we have a REST channel, but how do we let others know about it? On the one hand, you can simply notify your partners and clients through documentation, wiki pages, or other non-automated means.

On the other hand, you can also supply auto-generated API documentation and OpenAPI definitions, like below. This means that API clients matching your services can be generated automatically.

Auto-generated API documentation index file screenshot.

Auto-generated API documentation service file screenshot.

And by the way, if you need a WSDL for SOAP clients, the generated documentation includes it too.

Invoking REST APIs

This is everything about REST channels today but one question may be still open. If channels are means for handling incoming connections then how does one make requests to REST API endpoints external to Zato? How can we invoke other people's microservices?

The answer is that this is what Zato's outgoing connections are for and we will cover REST outgoing connections in a future post.

Learn More

If you are interested in building scalable and reusable API systems, you can start now by visiting the Zato main page, familiarize yourself with the extensive documentation, or jumping straight into the first part of the tutorial.

Be sure to visit our Twitter, GitHub, and Gitter communities too!

REST API Web Protocols microservice Web Service

Opinions expressed by DZone contributors are their own.

Related

  • Breaking Up a Monolithic Database with Kong
  • User-Friendly API Publishing and Testing With Retrofit
  • Building a Secure REST API with OpenID Connect
  • Building REST API Backend Easily With Ballerina Language

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!