使用aiohttp向Gmail API发GET请求携带access token返回401错误如何解决
你遇到的401错误核心是手动维护的CRED静态变量和谷歌客户端实际生效的token不一致导致的,具体原因和修复方案如下:
- 静态CRED变量未同步更新:你在
authenticate方法中如果触发了token刷新逻辑,谷歌客户端会自动生成新的access token,但你本地存的CRED对象还是旧值,哪怕你判断没过期,实际已经失效。官方build生成的service会自动读取当前生效的最新token,所以调用正常。 - 修复方案1:直接从实例中持有的creds对象读取token,不要用静态CRED变量。你可以在
authenticate方法中将creds存为实例变量,之后调用接口时直接取实例内的token构造请求头即可。 - 修复方案2:每次刷新token后同步更新你存储的CRED数据,确保谷歌客户端生成的最新token和你手动维护的CRED完全一致。
- 额外校验项:确认
GET_MAIL_FROM_ID_URL的格式正确,正确的请求地址格式为https://gmail.googleapis.com/gmail/v1/users/{userId}/messages/{id}
修改后的参考代码:
def authenticate(self): # 原有认证逻辑不变 creds = None if os.path.exists('token.json'): creds = Credentials.from_authorized_user_file('token.json', SCOPES) if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( 'credentials.json', SCOPES) creds = flow.run_local_server(port=0) with open('token.json', 'w') as token: token.write(creds.to_json()) # 新增:将有效creds存为实例变量,方便后续调用 self.creds = creds self.service = build('gmail', 'v1', credentials=creds) async def __get_email_by_id(self, id): url = GET_MAIL_FROM_ID_URL.format("me", id) # 修改:从实例creds中读取最新有效token headers = {'Authorization': 'Bearer {}'.format(self.creds.token)} async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: # aiohttp内置json解析方法,无需手动loads return await response.json()
内容的提问来源于stack exchange,提问作者NANDU KISHORE
相关产品推荐
相关产品推荐

