如何从Zato服务中调用REST APIs

63 阅读3分钟

外发连接

类似于通道负责通过REST或其他通信手段授予对你的服务的访问,是出站连接(outconns,作为缩写)让服务访问Zato外部的资源,包括REST APIs。

这里是一个REST出站连接的定义样本。

Zato web-admin outgoing connections Zato web-admin creating a REST outgoing connection

Python的实现很快就会出现,但现在,让我们观察一下,将两者分开有几个突出的优点。

  • 相同的出站连接可以被多个服务使用

  • 配置只在一个地方维护--任何变化都会立即反映在所有的服务器上,服务可以使用新的配置而不会中断

REST输出连接的大多数选项与通道的含义相同,但TLS CA证书可能需要特别注意。这个选项决定了如果一个REST端点使用HTTPS而不是HTTP来调用会发生什么,如何检查远程端的TLS证书。

该选项可以是以下之一。

  • 默认捆绑 - 一个内置的CA证书捆绑将被用于验证。如果你调用的API是一个众所周知的公共API,其端点由某个公共证书机构签署,那么这与Mozilla使用的捆绑方式相同,是一个不错的选择。
  • 如果你上传你自己的CA证书,它们可以用于验证外部REST API - 例如,你的公司或商业伙伴可能有自己的内部CA。
  • 跳过验证 - 完全不进行验证,任何TLS证书都会被接受,包括自签名的。通常情况下,这个选项不应该用于非开发目的。

Python代码

下面是一个使用出站连接的服务示例。

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class GetUserDetails(Service):
    """ Returns details of a user by the person's name.
    """
    name = 'api.user.get-details'

    def handle(self):

        # In practice, this would be an input parameter
        user_name = 'john.doe'

        # Name of the connection to use
        conn_name = 'My REST Endpoint'

        # Get a connection object
        conn = self.out.rest[conn_name].conn

        # A single dictionary with all the parameters,
        # Zato will know where each one goes to.
        params = {
            'name': user_name,
            'app_id': 'Zato',
            'app_version': '3.2'
        }

        # We are responsible for catching exceptions
        try:

            # Invoke the endpoint
            response = conn.get(self.cid, params)

            # Log the response
            self.logger.info('Response `%s`', response.data)

        # We caught an exception - log its details
        except Exception as e:
            self.logger.warn('Endpoint could not be invoked due to `%s`', e.args[0])

首先,我们获得一个连接句柄,然后调用端点并处理一个响应,在这种情况下,这仅仅意味着将其内容输出到服务器日志。

在这个例子中,我们使用了一个恒定的用户名和查询字符串,但在实践中,它们可能会根据用户的输入而产生。

注意'params'字典--当你调用这个服务时,Zato会知道'name'应该进入URL路径,但所有其余的参数将进入请求的查询字符串。同样,这给了你额外的灵活性,例如,如果端点的URL从路径参数变为查询字符串,该服务将继续工作而不发生任何变化。

还要注意的是,我们要负责捕捉和处理因调用REST端点而产生的潜在异常。

最后--因为传出连接的数据格式是JSON,你不需要自己去/序列化它,'response.data'的内容已经是一个从JSON响应中读取的Python dict。

在这一点上,服务已经准备好被调用了--比方说,通过REST、AMQP或来自调度器--当你这样做时,这里是将在服务器日志中看到的输出。

INFO - Response `{'user_id': 123, 'username': 'john.doe', 'display_name': 'John Doe'}`

现在,你可以扩展它来调用其他系统,从SQL数据库获取数据或与其他API集成。

接下来的步骤

学习如何整合API和构建系统。完成后,你将拥有一个多协议服务,它代表了银行系统中经常出现的样本场景,有几个应用程序合作为其调用者提供一个单一的、一致的API。