解释一个针对卡托 API 的 Python 脚本

本文介绍了 Cato API,并分析了一个示例 Python 应用程序。

介绍

Cato API 根据GraphQL 规范实现。 尽管 GraphQL 旨在生成易于使用的 API,但学习如何使用新技术仍然需要开发者投入时间。 本文档的目标是减少这一投入,并介绍一个小型 Python 应用程序,该应用程序执行admins Cato API 调用并简单返回为账户定义的管理员数量。 通过这样做,向读者介绍了 Cato GraphQL API 应用程序中的最重要元素。

注意

注意:

预期读者对以下内容有基本理解:

  • 编写脚本或编程(例如,您熟悉变量和代码库等概念)

  • JSON 规范(例如,您已处理过 JSON 文档)

  • 网络(例如,您知道 HTTP 协议的存在以及服务器是什么)

对 Python 语言的某些经验会有帮助,但仍然可以理解本文。

基本 Cato API 应用程序演练

此处提供的应用程序是用 Python 编写的,并使用 Cato API admins调用来检索为账户定义的管理员总数。  选择 Python 和admins API 调用的原因是:

  • Python 是一种易于阅读和理解的非常常用的语言

  • admins API 调用可以用来创建一个非常简单的调用 Cato GraphQL API 的示例

示例程序是基本的,不包含错误检查。  程序仅仅打印出为账户定义的管理员总数。 

注意

注意: Cato API 不与任何特定编程语言绑定。  可以使用任何能够使用 HTTP POST 功能和处理 JSON 文档的语言实现应用程序。  

示例程序概览

此示例程序简单,不包括任何决策逻辑或代码来重复操作。  通过将一些代码行合并到单行中,可以使其更短。  额外的代码行被包含以便于解释正在发生的事情。

# 导入 Python 库代码
import os
import urllib.request
import ssl
import json

# 从环境变量中获取 Cato API 密钥
cato_api_key = os.getenv("CATO_API_KEY")

# 创建要发送的 GraphQL 请求
get_total_admins = '''{
    admins (accountID: 12345) {
        total        
    }
}'''
graphql_query = {'query': get_total_admins}

# 构建 http 请求
cato_api_url = "https://api.catonetworks.com/api/v1/graphql2"
headers = {'x-api-key': cato_api_key,
           'Content-Type':'application/json'}
unverified_ctx = ssl._create_unverified_context()
json_post = json.dumps(graphql_query)
json_post_encoded = json_post.encode()
request = urllib.request.Request(url=cato_api_url, data=json_post_encoded, headers=headers)

# 发送查询并将响应转换为 Python 字典
response = urllib.request.urlopen(request, context=unverified_ctx, timeout=30)
json_response_encoded = response.read()
json_response = json_response_encoded.decode()
get_admins_total_result = json.loads(json_response)

# 从返回的数据中提取总数并打印出来
total = get_admins_total_result['data']['admins']['total']
print('在您的账户中定义的管理员总数为: {}'.format(total))

注意

重要! 该程序作为演示如何使用 Python 访问 Cato API 提供。 它不是官方 Cato 发布,不保证提供支持。 错误处理被限制为脚本与 API 配合所需的最低限度,可能不适合生产环境。

所有问题或反馈请发送至api@catonetworks.com

下面提供的图解显示了程序运行时事件的顺序:

  1. 程序创建一个 JSON 文档并发送到 Cato API GraphQL 服务器。

  2. Cato API GraphQL 服务器检查确保 JSON 文档中定义的 API 调用正确,并从 Cato 服务获取请求的数据。

  3. Cato API GraphQL 服务器以 JSON 文件形式将数据返回给程序。

Cato_API_FLow.jpeg

导入 Python 库代码

使用 Python 进行示例程序的原因之一是丰富的库集。  这些库提供了能够处理广泛任务的函数和对象。  我们将逐个浏览每个导入的库,并提供注释来解释为什么需要它。

import os
  • os 库提供的函数允许代码访问操作系统环境变量中的数据。

import urllib.request
  • 来自urllib库的request模块定义了Request类,该类创建可以处理通过 URL 访问远程服务器通信的对象。

  • 这将使发送 Cato API 请求到 Cato GraphQL API 服务器成为可能

import ssl
  • ssl 库需要创建一个自定义未经验证的上下文,以便发送请求到 Cato GraphQL API 服务器。

import json
  • 该库包含功能,使可能将 Python 字典转换为 JSON 字符串,反之亦然。

  • 这种在两种不同格式之间转换的能力使编写能够处理 JSON 文档的代码更简单。

获取 Cato API 密钥

这行代码使用getenv库函数从环境变量中读取 API 密钥并将其分配给变量。

cato_api_key = os.getenv("CATO_API_KEY")

Cato GraphQL 服务器期望在 nHTTP 头中接收此密钥。  由于 GraphQL 规范不将授权作为标准的一部分,因此密钥未在 JSON 文档中提供。  在 JSON 文档中包含授权将违反规范。  Cato API 密钥通过 Cato 管理应用程序生成。  有关创建 API 密钥的更多信息,请参见生成 Cato API 的 API 密钥

注意

警告! 虽然可以将 Cato API 密钥硬编码到您的代码中,但强烈建议不要这样做。

创建待发送的 GraphQL 请求

接下来的几行代码创建一个包含一个键/值对的 Python 目录。  条目值是使用定义将发送到 GraphQL 服务器的查询的 Python 多行字符串构建的。

get_total_admins = '''{
    admins (accountID: 12345) {
        total    
    }
}'''
graphql_query = {'query': get_total_admins}

Cato GraphQL 服务器将解读此字符串为:执行函数get_total_admins,向其传递两个参数(accountID 和 type)并且仅返回实体的"total"数量。  或者更直接地说,“返回为示例账户 #12345 定义的管理员实体总数”。  这个特定的admins API 调用示例说明了 GraphQL API 的一个重要优势

  • 服务器仅返回应用程序请求的数据

事实上,admins调用可以返回更多数据。  例如,应用程序可以请求admins返回有关每个管理员的详细信息。  然而,此应用程序只需知道管理员的总数。  GraphQL 的这一特性避免了所谓的过度获取,并且可以大大简化实现应用程序所需的代码。

构建 HTTP 请求

在程序的这一部分构建了请求对象。  这个对象将用于通过 HTTPS 发送 API 调用给 GraphQL 服务器。 此请求对象需要的信息由一些需要首先创建的其他对象提供。   首先,构建一个简单的字符串对象来包含请求对象将发送查询的 GraphQL 服务器 URL。

cato_api_url = "https://api.catonetworks.com/api/v1/graphql2"

注意

注意: 一种 GraphQL API 对所有 API 调用只使用一个 URL。  调用的细节,例如参数,在 JSON 文档中提供。  这与 REST API 不同,后者对每个 API 调用使用不同的 URL,并通过将参数附加到 URL中传递给调用。  这种使用不与参数混杂在一起的唯一 URL 被认为是 GraphQL API 的另一优点。 

然后创建一个字典,该字典定义了两个 HTTP 头。  这些头用于由请求对象构建 GraphQL 服务器将接受的 HTTP POST 请求。  没有这些头,HTTP POST 请求将被服务器拒绝。

headers = {'x-api-key': cato_api_key,           
           'Content-Type':'application/json'}

下一行代码创建一个 SSL 上下文对象。 Python 使用此对象来确定如何加密 HTTP 请求并使用传输层安全性(TLS)发送。 在此,我们正在创建一个不验证证书的 SSL 上下文对象。 这样做是为了避免在网络受到上游 TLS 检查时出现证书错误。

unverified_ctx = ssl._create_unverified_context()

注意

重要! 使用未经验证的 SSL 上下文对象意味着将不会检查以确保证书有效。 卡托网络建议您绝不要在生产中使用这样的做法。 如何加强安全的细节超出本文档的范围。

接下来的两行代码将包含 Cato API 调用的 Python 字典转换为字符串并将该字符串编码为字节。  第二步是允许字符串通过网络传输。

json_post = json.dumps(graphql_query)
json_post_encoded = json_post.encode()

最后创建请求对象,现在程序准备发送get_total_admins调用到服务器。

request = urllib.request.Request(url=cato_api_url, data=json_post_encoded, headers=headers)

发送查询和处理响应

这里程序通过调用 urllib 库的urlopen函数发送请求到 GraphQL 服务器。  调用此函数将导致返回一个 HTTPResponse 对象。  

response = urllib.request.urlopen(request, context=unverified_ctx, timeout=30)

注意

警告! 调用urlopen函数可能会导致错误。  例如,GraphQL 服务器可能由于语法错误而拒绝请求,或者网络问题可能导致超时(即 30 秒后无响应)。  这里没有处理这些错误。

urlopen 函数返回的对象包含一个 body 字段,其中保存服务器返回的 JSON 文档。  可以通过执行其read方法从对象中提取,该方法返回字节对象。  然后通过调用字节对象的 decode 方法将此字节对象转换为字符串对象。

json_response_encoded = response.read()
json_response = json_response_encoded.decode()

此解码字符串包含一个 JSON 文档,类似于以下内容:

{    
    "data" : {
         "admins" : {
              "total": 4
         }
    }
}

正如您所见,返回数据的格式与发送到服务器的请求格式非常相似。  这是一种有意为之的设计,并且是使用 GraphQL 规范实现 API 的另一种优势。  这种方法通过保持返回数据与请求的格式相同来简化应用程序编码。

程序中这一部分的最后一行代码使用 json 库函数 'loads' 将返回的 JSON 字符串转换为 Python 嵌套字典。  

get_total_admin_result = json.loads(json_response)

从返回的数据中提取总数并打印出来

代码的最后两行从服务器返回的 total 字段中提取值并将其打印到控制台。 

total = get_total_admins_result['data']['get_total_admins']['total']
print('为您的账户定义的管理员总数是: {}'.format(total)) 

输出将如下所示:

为您的账户定义的管理员总数是: 4

总结

本文档的目标是向读者展示使用 Cato API 是多么简单。  未包含 Cato API 的详细信息,并且没有编写代码来处理错误。  而是使用一个简单的 Python 程序来突出显示 Cato API 应用程序的最重要元素。  这些元素包括:

  • 创建 Cato API 调用并将其添加到 JSON 文档中

  • 获得 Cato API 密钥

  • 创建包含 Cato API 密钥的 HTTP 头并定义数据格式(JSON)

  • 使用已加密的 HTTP POST 命令通过 Cato GraphQl API 服务器发送 JSON 文档(以字节编码)

  • 将服务器返回的响应对象转换为 JSON 文档

  • 将 JSON 文档转换为程序可使用的格式

这篇文章有帮助吗?

5 人中有 5 人觉得有帮助

0 条评论