【问题标题】:How to determine required REST Get requests formatting in Python如何在 Python 中确定所需的 REST Get 请求格式
【发布时间】:2021-04-08 18:47:17
【问题描述】:

对 REST API 完全陌生,仍在学习 python,所以我为一个简单的问题和一个菜鸟道歉。任何帮助表示赞赏。

我正在尝试使用 GET 请求从服务器中提取数据。他们的网站上提供了这样做的说明:Ayyeka REST API,我也阅读了他们的help documentation。它表明您必须使用 swagger_client,但我无法使其正常工作。相反,我使用 requests 模块拼凑了一些代码,我似乎使用 OAuth2 正确获取了令牌。

import os, string, time
from requests.auth import HTTPBasicAuth
from requests.structures import CaseInsensitiveDict
import base64

#credentials
client_id= "[client id goes here]"
client_secret = "[secret goes here]"
secret64 = base64.b64encode(bytes(client_id + ':' + client_secret, 'utf-8')).decode('utf-8')

#time and stream to pull data from
dtime = 1617821133
AyyekaChannel_text = '183534'

token_url = 'https://restapi.ayyeka.com/auth/token'
base_url = 'https://restapi.ayyeka.com '

auth = HTTPBasicAuth(client_id, client_secret)
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url='https://restapi.ayyeka.com/auth/token', auth=auth)
access_token = token['access_token']

headers = {'Authorization': 'Bearer ' + access_token}
response = requests.get(url=base_url,headers=headers)

token 返回:

{'access_token': '[token string appears here]', 'token_type': 'JWT', 'expires_in': 3600,'expires_at': 1617909733.2390773}

现在我被卡住了,不知道如何通过 GET 传递它来获取身份验证令牌,也不知道如何使用 REST 命令来提取数据。我在正确的轨道上吗?完全离题? response 只是返回一堆错误,但我知道这无论如何都不对,但我无法弄清楚下一步,因为他们的文档使用了 swagger_client 。我不确定我是否应该回去尝试让 swagger_client 工作,或者这是否应该工作?

【问题讨论】:

  • 使用请求会话确保 cookie 在每次 GET/PUT/POST 时都可以访问
  • 感谢您的帮助!你介意详细说明一下吗?虽然熟悉python,但我对这样的事情完全是新手。我觉得自己像个傻瓜,但只是在努力学习!

标签: python rest python-requests swagger


【解决方案1】:

很难给出一个很好的例子,因为我无法访问他们的帮助文档。也就是说,看起来您正在获取 JWT 令牌,并且您正在传递带有所述令牌的标头。我很想知道您在响应中遇到了什么错误。您可以使用 response.status_code 和 response.text 进行检查。

您的 base_url 变量 base_url = 'https://restapi.ayyeka.com ' 中有一个空格,而不是 base_url = 'https://restapi.ayyeka.com'。这可能是你问题的一部分。您也没有附加任何实际的 API 端点。此外,他们的文档在他们的 curl 示例中显示应该有一个附加到该 URL 的版本(请参阅下面我的 base_url)。

正如 barny 所说,您可能希望在这里使用 requests.Session()。您在评论中询问了如何做到这一点,方法如下:

dtime = 1617821133
AyyekaChannel_text = "183534"

base_url = "https://restapi.ayyeka.com/v2.0"

session = requests.Session()
session.headers.update({"Authorization": f"Bearer {access_token}"})

params = {
    "sampleID": AyyekaChannel_text,
    "backfillHours": dtime,
}

session.get(url=f"{base_url}/sample/batch", params=params)

话虽如此,文档中提到了backfillHours

指定从数小时前开始发送样本。例如,如果 backfillHours 值为 24,则这是一个提供过去 24 小时的所有样本的请求

我不知道您在此处对 dtime 的预期用途是什么,但显然 1617821133 就像过去 180,000 多年前一样,但我在这里使用它作为示例,说明如何将该值作为请求中的查询参数,假设它是一个合理的值。

您可能还需要使整个事情面向对象。这是一个非常简短的示例,用于说明目的:

class AyyekaClient:
    """A client implementing the Ayyeka API."""

    def __init__(self, client_id: str, client_secret: str):
        self.base_url = "https://restapi.ayyeka.com/v2.0"
        self.client_id = client_id
        self.client_secret = client_secret
        self.auth = HTTPBasicAuth(client_id, client_secret)
        self.client = BackendApplicationClient(client_id=self.client_id)
        self.oauth = OAuth2Session(client=self.client)
        self.session = requests.Session()
        self.session.hooks["response"] = [self.raise_for_status]
        self.refresh_access_token()

    def raise_for_status(response, *args, **kwargs):
        """Requests event hook to call raise_for_status on every request."""
        response.raise_for_status()

    def refresh_access_token(self):
        """Get a fresh access token."""
        token = self.oauth.fetch_token(token_url="https://restapi.ayyeka.com/auth/token", auth=self.auth)["access_token"]
        self.session.headers.update({"Authorization": f"Bearer {token}"})

    def get_sample_scalar_batch(self, sample_id: str, backfill_hours: int) -> requests.Response:
        """Get a Batch of New SamplesScalar."""
        params = {"sampleID": sample_id, "backfillHours": backfill_hours}
        return self.session.get(url=f"{self.base_url}/sample/batch", params=params)

然后你会像这样实现那个类:

ayyeka = AyyekaClient(client_id="123456", client_secret="78910112")
response = ayyeka.get_sample_scalar_batch(sample_id, backfill_hours)
print(response.text)
print(response.json())

这些 JWT 令牌只有 1 小时的生命周期,因此您有时需要调用 ayyeka.refresh_access_token() 或进行某种错误处理,如果请求因 401/403 错误而失败,您可以刷新令牌并尝试再次请求。该方法将自动获取新令牌并更新会话的 Authorization 标头以使用该令牌。

这只是一个说明性示例,说明您如何在此处使用类。我没有花太多心思在这上面。您可以将其余的 API 端点实现为此类上的方法,然后在单独的脚本/模块中实现客户端。

【讨论】:

  • 哇这么详细!我将按照您的所有建议进行工作。非常感谢您的时间和精力!
  • 谢谢@RossV - 如果您有时间,您介意将其标记为已接受的答案吗?谢谢!
猜你喜欢
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 2015-07-02
  • 2011-09-09
  • 1970-01-01
相关资源
最近更新 更多