如何移除Discord REST API响应中的分块传输相关多余字符?
解决Discord OAuth2 Token响应的分块编码解析问题
你遇到的问题是因为Discord返回的响应使用了分块编码(Transfer-Encoding: chunked),直接分割\r\n\r\n提取的响应体包含分块长度标识(如de)和结束标记(如0),导致json.loads无法解析。下面是两种可靠的解决方法:
方案一:使用成熟HTTP库(推荐)
直接用requests库处理HTTP请求,它会自动处理分块编码、头解析和错误处理,代码简洁且不易出错:
import requests def request_access_token(client_id: str, client_secret: str, code: str, redirect_uri: str) -> dict: url = "https://discord.com/api/oauth2/token" data = { "client_id": client_id, "client_secret": client_secret, "grant_type": "authorization_code", "code": code, "redirect_uri": redirect_uri } response = requests.post(url, data=data) response.raise_for_status() # 主动抛出HTTP错误,方便调试 return response.json()
方案二:手动解析分块编码(原生Socket)
如果必须使用原生Socket,需要严格按照HTTP分块编码的规范解析响应体,去掉分块长度标识和分隔符:
import socket import ssl import json def request_access_token(client_id: str, client_secret: str, code: str, redirect_uri: str) -> dict: host = "discord.com" path = "/api/oauth2/token" port = 443 data = f"client_id={client_id}&client_secret={client_secret}&grant_type=authorization_code&code={code}&redirect_uri={redirect_uri}" request = f"POST {path} HTTP/1.1\r\nHost: {host}\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: {len(data)}\r\nConnection: close\r\n\r\n{data}" context = ssl.create_default_context() with socket.create_connection((host, port)) as sock: with context.wrap_socket(sock, server_hostname=host) as ssock: ssock.sendall(request.encode()) response = b"" while True: chunk = ssock.recv(1024) if not chunk: break response += chunk # 分离HTTP响应头和响应体 header_part, body_part = response.split(b"\r\n\r\n", 1) # 解析分块编码数据的函数 def parse_chunked_data(chunked_data): raw_body = b"" remaining_data = chunked_data while remaining_data: # 提取分块长度(十六进制字符串) length_line, remaining_data = remaining_data.split(b"\r\n", 1) chunk_length = int(length_line, 16) if chunk_length == 0: # 分块结束标记 break # 提取当前分块的内容 raw_body += remaining_data[:chunk_length] # 跳过内容后的\r\n分隔符 remaining_data = remaining_data[chunk_length + 2:] return raw_body # 判断响应是否使用分块编码 headers = header_part.decode().split("\r\n") is_chunked = any("Transfer-Encoding: chunked" in header for header in headers) if is_chunked: body_content = parse_chunked_data(body_part) else: body_content = body_part return json.loads(body_content.decode())
关键说明:
分块编码的结构是:
- 每块开头是十六进制的长度值 +
\r\n - 接着是对应长度的内容 +
\r\n - 最后以
0\r\n\r\n表示所有分块结束
手动解析时需要严格按照这个结构提取内容,不能靠简单的字符串替换,否则遇到复杂分块场景(比如多块、长度带扩展参数)会出错。
内容的提问来源于stack exchange,提问作者RGCSERG
相关产品推荐
相关产品推荐

