google-auth-library-python
google-auth-library-python copied to clipboard
_aiohttp_requests.AuthorizedSession is not decompressing Google Drive API response
Environment details
- OS: Arch Linux
- Python version: 3.10.0
- pip version: 21.2.4
-
google-auth
version: 2.3.3
Steps to reproduce
- Create a service account and generate a JSON key for it
- Create a
google.oauth2._service_account_async.Credentials
instance with the scope https://www.googleapis.com/auth/drive.metadata.readonly - Create a
google.auth.transport._aiohttp_requests.AuthorizedSession
instance using the credentials - Make a GET request similar to
session.request("GET", "https://www.googleapis.com/drive/v3/files/{fileId}")
replacingfileId
with the file identifier of a file (Google Sheet, Google Doc, etc.) that you shared with the service account - The request you get back will be an
aiohttp.ClientResponse
instance and the body will still be compressed using gzip. Therefore, if you attempt to useresponse.json()
it will fail when attempting to decode it
I was able to temporarily overcome this by wrapping the aiohttp.ClientResponse
in _aiohttp_requests._CombinedResponse
and using the content()
method which has logic to decompress the payload.
Let me know if perhaps I'm using the interface wrong or if it would be helpful for me to give additional context, thanks!
Hi @tstodden,
That looks like a reasonable approach given the current code - I get similar results with the following code snippet constructed from your reproduction steps:
import asyncio
from google.auth.transport import _aiohttp_requests
from google.oauth2 import _service_account_async
credentials = _service_account_async.Credentials.from_service_account_file(
"/path/to/service_account.json",
scopes=["https://www.googleapis.com/auth/drive.metadata.readonly"],
)
file_id = "my-file-id"
async def main():
async with _aiohttp_requests.AuthorizedSession(
credentials=credentials
) as authed_session:
response = await authed_session.request(
"GET", f"https://www.googleapis.com/drive/v3/files/{file_id}"
)
response = _aiohttp_requests._CombinedResponse(response)
content = await response.content()
print(content)
asyncio.run(main())
I'm not sure if the intent was that the additional manual wrapping would be required. I'll take a closer look at the history of the aiohttp transport and get back to you.