4. RESTful API 接口对接:HTTP/HTTPS 协议、RESTful 规范、请求/响应封装、常见 API 认证方式

数据源对接中,八成以上都是 RESTful API。说白了,就是通过 HTTP 协议跟远程服务“对话”。我最早接触时以为只是发个 GET 请求那么简单,结果被各种状态码和认证搞得焦头烂额。这一节咱们把关键点捋清楚。

4.1 HTTP/HTTPS 协议要点

HTTP 是应用层协议,基于 TCP。HTTPS 就是在外面套了一层 TLS/SSL。我个人习惯这么记:HTTP 是明信片,谁都能看;HTTPS 是信封,只有收件人能拆。

  • 请求方法:GET(查)、POST(增)、PUT(全量改)、PATCH(部分改)、DELETE(删)。
  • 状态码:2xx 成功,3xx 重定向,4xx 客户端错误,5xx 服务端错误。常见的 200、201、204、400、401、403、404、500。
  • Header:Content-Type、Authorization、Accept、User-Agent 等。特别留意 Content-Type: application/json。
我的经验:调试时先用 curl 模拟一遍,避免代码里藏着“隐形”的 Header 问题。比如服务端要求带 X-Request-ID,你忘了传,可能一直 400。

4.2 RESTful 设计规范

RESTful 不是协议,而是一套设计风格。核心是用资源路径 + 动词来表达操作。

  • 资源用名词复数:/users、/orders/{id}。不要用动词,比如 /getUser。
  • 无状态:每次请求携带全部必要信息,服务端不保存会话。
  • 版本化:路径里加 /v1 或 Header 里指定。
  • 查询参数:?page=1&size=20 用于分页、排序、过滤。
我曾经踩过的坑:对接一个内部系统,他们把删除设计成 POST /user/delete?id=xxx。这完全是 RPC 风格,破坏了可读性。后来我强制要求对方按 RESTful 改造,否则维护成本太高。

4.3 请求与响应封装实践

封装是让代码干净的关键。我习惯写一个 ApiClient 类,统一处理超时、重试、日志。

import requests
from requests.adapters import HTTPAdapter

class ApiClient:
    def __init__(self, base_url, timeout=10):
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        self.session.mount('https://', HTTPAdapter(max_retries=3))
        self.timeout = timeout

    def request(self, method, path, **kwargs):
        url = f"{self.base_url}/{path.lstrip('/')}"
        kwargs.setdefault('timeout', self.timeout)
        resp = self.session.request(method, url, **kwargs)
        resp.raise_for_status()  # 非 2xx 抛异常
        return resp.json()

注意几个细节:

  • 超时一定要设,不然网络挂了你代码也跟着挂。
  • 重试策略用指数退避,别一失败就猛刷。
  • 响应解析前先检查 Content-Type,防止拿到的不是 JSON。
避坑指南:有些服务端返回的 HTTP 状态码是 200,但 body 里带 {"code": 1, "msg": "error"}。这种“伪成功”只能靠业务判断,别全信状态码。

4.4 常见 API 认证方式

方式原理适用场景安全性
Basic AuthBase64(用户名:密码) 放 Header内部测试、简单系统低(必须配合 HTTPS)
静态字符串,Header 或参数传递开放平台、调用量控制中(易泄露,需定期轮换)
OAuth2授权码/密码/客户端模式获取 第三方授权、移动端高(支持刷新、作用域)
JWT自包含 ,签名校验无状态服务、微服务间高(但 有效期内无法撤销)

我个人最常用的是 OAuth2 客户端凭证模式。对于内部系统,直接配一个长期有效的 也能跑,但要记得加 IP 白名单。

# 使用  示例
headers = {'Authorization': 'Bearer YOUR_'}
response = client.request('GET', '/v1/datasources', headers=headers)
曾经的血泪教训:有一次对接厂家的 OAuth2,他们把 access_ 有效期设成 1 小时,但刷新接口有并发限制。我同时起了 10 个任务,全部过期后一齐刷新,结果被限流封了半小时。后来我强制加了 刷新锁和提前刷新机制。
RESTful API 对接核心流程 客户端 构建请求 (Method/URL/Header/Body) HTTPS 认证方式 Basic / / OAuth2 / JWT 服务器 资源 CRUD 操作 响应 (Status + Body) 解析 & 错误处理 关键点:每一步都需考虑超时、重试、认证失效、非预期状态码。 建议在客户端做 提前刷新、请求幂等性设计。

整个流程串起来就是:客户端构造请求 -> 通过 HTTPS 发送 -> 服务端认证 -> 执行业务 -> 返回响应 -> 客户端解析。任何一个环节都可能出幺蛾子。我的做法是先在接口文档里确认认证方式,然后写一个最小 demo 跑通再做封装。