
本文介绍在 python 中调用外部 api(如 emby 服务)后,如何正确解析 json 响应、健壮提取多个嵌套字段(如 accesstoken、serverid、user.id),并构造符合 authentik 属性映射要求的结构化字典,同时规避语法错误与运行时异常。
本文介绍在 python 中调用外部 api(如 emby 服务)后,如何正确解析 json 响应、健壮提取多个嵌套字段(如 accesstoken、serverid、user.id),并构造符合 authentik 属性映射要求的结构化字典,同时规避语法错误与运行时异常。
在集成第三方服务(如 Emby)到身份平台(如 Authentik)时,常需通过 HTTP 请求动态获取用户凭证或上下文信息,并将多个响应字段映射为自定义 HTTP 头(如 X-Emby-Token)。但直接在 return 语句中嵌套访问未校验的 JSON 键会导致 KeyError,而将 return 写在函数体外则引发 SyntaxError: 'return' outside function —— 这正是原始代码的根本问题。
✅ 正确做法是:将逻辑封装为函数,并在 try/except 中分步提取、赋默认值,确保结构稳定、可读性强。以下是推荐实现:
import json
from urllib.parse import urlencode
from urllib.request import Request, urlopen
def fetch_emby_headers(base_url="http://myserver:80", api_key="xyz", request_data=None):
"""
向 Emby 后端发起 POST 请求,提取 AccessToken、ServerId 和 User.Id,
返回符合 Authentik 属性映射格式的字典。
"""
if request_data is None:
request_data = {} # 替换为实际请求体,如 {"UserId": "xxx"}
endpoint = f"/backend?api_key={api_key}"
postdata = json.dumps(request_data).encode("utf-8")
headers = {"Content-Type": "application/json; charset=UTF-8"}
try:
req = Request(base_url + endpoint, data=postdata, method="POST", headers=headers)
with urlopen(req, timeout=10) as response:
resp_json = json.loads(response.read().decode("utf-8"))
# 安全提取字段:支持嵌套访问 + 默认值兜底
access_token = resp_json.get("AccessToken", "null")
server_id = resp_json.get("ServerId", "null")
user_id = resp_json.get("User", {}).get("Id", "null") # 避免 KeyError
except (json.JSONDecodeError, UnicodeDecodeError):
access_token = server_id = user_id = "null"
except Exception as e:
print(f"[WARN] HTTP or network error: {e}")
access_token = server_id = user_id = "null"
return {
"ak_proxy": {
"user_attributes": {
"additionalHeaders": {
"X-Emby-Token": access_token,
"X-Emby-ServerId": server_id,
"X-Emby-UserId": user_id
}
}
}
}
# ✅ 调用示例(Authentik 属性映射脚本中使用)
# result = fetch_emby_headers(
# base_url="http://emby.example.com:8096",
# api_key="a1b2c3d4e5f6",
# request_data={"Username": "john_doe"}
# )
# print(json.dumps(result, indent=2))? 关键注意事项:
-
必须定义函数:
return只能在函数、方法或 lambda 内使用;裸露的return会触发语法错误。 -
优先使用
.get()链式访问:替代硬编码responddata['User']['Id'],避免因缺失User字段导致崩溃。 -
显式超时与异常分类:添加
timeout=10防止请求挂起;区分 JSON 解析异常与网络异常,便于调试。 -
字段命名一致性:Authentik 模板中 Header 名(如
X-Emby-Token)需与文档严格一致,注意大小写。 -
生产环境建议升级:
urllib.request功能基础,推荐改用requests库(支持 session、重试、更清晰的异常类型),例如:requests.post(url, json=request_data, headers=headers, timeout=10)。
该方案兼顾健壮性、可维护性与 Authentik 集成规范,可直接用于属性映射(Property Mapping)的 Python 脚本中。


















