Skip to content

Get response headers even with 4xx return code #367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions gql/transport/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ async def execute(

async with self.session.post(self.url, ssl=self.ssl, **post_args) as resp:

# Saving latest response headers in the transport
self.response_headers = resp.headers

async def raise_response_error(resp: aiohttp.ClientResponse, reason: str):
# We raise a TransportServerError if the status code is 400 or higher
# We raise a TransportProtocolError in the other cases
Expand Down Expand Up @@ -325,9 +328,6 @@ async def raise_response_error(resp: aiohttp.ClientResponse, reason: str):
if "errors" not in result and "data" not in result:
await raise_response_error(resp, 'No "data" or "errors" keys in answer')

# Saving latest response headers in the transport
self.response_headers = resp.headers

return ExecutionResult(
errors=result.get("errors"),
data=result.get("data"),
Expand Down
47 changes: 47 additions & 0 deletions tests/test_aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,53 @@ async def handler(request):
assert "401, message='Unauthorized'" in str(exc_info.value)


@pytest.mark.asyncio
async def test_aiohttp_error_code_429(event_loop, aiohttp_server):
from aiohttp import web
from gql.transport.aiohttp import AIOHTTPTransport

async def handler(request):
# Will generate http error code 429
return web.Response(
text="""
<html>
<head>
<title>Too Many Requests</title>
</head>
<body>
<h1>Too Many Requests</h1>
<p>I only allow 50 requests per hour to this Web site per
logged in user. Try again soon.</p>
</body>
</html>""",
content_type="text/html",
status=429,
headers={"Retry-After": "3600"},
)

app = web.Application()
app.router.add_route("POST", "/", handler)
server = await aiohttp_server(app)

url = server.make_url("/")

transport = AIOHTTPTransport(url=url)

async with Client(transport=transport) as session:

query = gql(query1_str)

with pytest.raises(TransportServerError) as exc_info:
await session.execute(query)

assert "429, message='Too Many Requests'" in str(exc_info.value)

# Checking response headers are saved in the transport
assert hasattr(transport, "response_headers")
assert isinstance(transport.response_headers, Mapping)
assert transport.response_headers["Retry-After"] == "3600"


@pytest.mark.asyncio
async def test_aiohttp_error_code_500(event_loop, aiohttp_server):
from aiohttp import web
Expand Down
49 changes: 49 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,55 @@ def test_code():
await run_sync_test(event_loop, server, test_code)


@pytest.mark.aiohttp
@pytest.mark.asyncio
async def test_requests_error_code_429(event_loop, aiohttp_server, run_sync_test):
from aiohttp import web
from gql.transport.requests import RequestsHTTPTransport

async def handler(request):
# Will generate http error code 429
return web.Response(
text="""
<html>
<head>
<title>Too Many Requests</title>
</head>
<body>
<h1>Too Many Requests</h1>
<p>I only allow 50 requests per hour to this Web site per
logged in user. Try again soon.</p>
</body>
</html>""",
content_type="text/html",
status=429,
headers={"Retry-After": "3600"},
)

app = web.Application()
app.router.add_route("POST", "/", handler)
server = await aiohttp_server(app)

url = server.make_url("/")

def test_code():
transport = RequestsHTTPTransport(url=url)

with Client(transport=transport) as session:

query = gql(query1_str)

with pytest.raises(TransportServerError) as exc_info:
session.execute(query)

assert "429, message='Too Many Requests'" in str(exc_info.value)

# Checking response headers are saved in the transport
assert hasattr(transport, "response_headers")
assert isinstance(transport.response_headers, Mapping)
assert transport.response_headers["Retry-After"] == "3600"


@pytest.mark.aiohttp
@pytest.mark.asyncio
async def test_requests_error_code_500(event_loop, aiohttp_server, run_sync_test):
Expand Down