Issue with request.ctx in response middleware

I’m having an issue with the following code:

@app.middleware('request')
async def _prepare(request):
    request.ctx.test = '1234'

@app.middleware('response')
async def _cleanup(request, response):
    test = request.ctx.test
    #test = getattr(request.ctx, 'test') # either one will produce the same exception

I’m getting this error
AttributeError: 'types.SimpleNamespace' object has no attribute 'test'

In the handler I’m able to access request.ctx.test just fine.

I’ve made this small example to help recreate the issue.

from sanic import Sanic
from sanic.response import HTTPResponse

app = Sanic("middleware_test")

@app.middleware("request")
async def _prepare(request):
    request.ctx.test = 'ASDF'

@app.middleware("response")
async def _cleanup(request, response):
    test = request.ctx.test

@app.route("/")
async def test(request):
    test = request.ctx.test
    return HTTPResponse("Got Test: %s" % test, content_type='text/html')

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8888)

If you run the code, you’ll notice the handler renders the response just fine, but if you look at the console output you’ll notice the traceback:

[2020-07-04 21:45:19 +0000] [21208] [ERROR] Exception occurred in one of response middleware handlers
Traceback (most recent call last):
  File "<path>/env/lib/python3.6/site-packages/sanic/app.py", line 977, in handle_request
    request, response, request_name=name
  File "<path>/env/lib/python3.6/site-packages/sanic/app.py", line 1281, in _run_response_middleware
    _response = await _response
  File "mwtest.py", line 12, in _cleanup
    test = request.ctx.test
AttributeError: 'types.SimpleNamespace' object has no attribute 'test'

Hi @verdebirth
What version of Sanic are you using? I’ve tried your snippet on sanic v20.3.0 and 20.6.3 and cannot reproduce the error. On both tests your snippet works fine.
Might need some more details about your setup to try to get to the bottom of this.

I’m running on sanic v20.6.3 and python 3.6.9

Edit: I built a fresh venv with python 3.8.3 and sanic 20.6.3 and replicated the problem. The typical behavior is that the response is delivered to the browser as if everything was fine, however you can see in the console that the response middleware breaks

@verdebirth
I understand your problem, I know what the typical behavior is and how your are experiencing your error, but simply cannot replicate it. Your response-middleware does not issue an error in my tests or within any of the Tox test environments conducted by Sanic. The test attribute of request.ctx can be read without error in the response-middleware. I’ve verified this by setting a breakpoint in the response-middleware and stepping through the instructions to lookup the attribute on the ctx variable.

I’ve tested it on Ubuntu 18.04 and ubuntu 20.04, with Python 3.6, 3.7 and 3.8, with Sanic v20.3.0 and v20.6.3

@ashleysommer
Fresh Ubuntu 18.04 install with Python 3.8 and sanix 20.3.0:

[2020-07-06 00:29:03 +0000] [2812] [INFO] Goin' Fast @ http://0.0.0.0:8888
[2020-07-06 00:29:03 +0000] [2812] [INFO] Starting worker [2812]
[2020-07-06 00:29:43 +0000] [2812] [ERROR] Exception occurred in one of responss
Traceback (most recent call last):
  File "/root/test/env/lib/python3.8/site-packages/sanic/app.py", line 976, in t
    response = await self._run_response_middleware(
  File "/root/test/env/lib/python3.8/site-packages/sanic/app.py", line 1281, ine
    _response = await _response
  File "mwtest.py", line 12, in _cleanup
    test = request.ctx.test
AttributeError: 'types.SimpleNamespace' object has no attribute 'test'

I installed Python3.8.3 on my Windows 10 desktop and was able to get a clean run on the same file. I’ll keep digging.

FWIW, I am running the same sample and not having a problem.

[2020-07-07 00:31:01 +0300] [544103] [INFO] Goin' Fast @ http://0.0.0.0:8888
[2020-07-07 00:31:01 +0300] [544103] [INFO] Starting worker [544103]
ASDF
[2020-07-07 00:31:04 +0300] - (sanic.access)[INFO][127.0.0.1:35932]: GET http://localhost:8888/  200 14

(I added a print statement in the response middleware)

I discovered the issue!
The reason the handler was rendering fine is because everything was fine! It was a missing favicon.ico causing a 404 causing the middleware to error.

I can confirm that 404s are still trying to run the response middleware.

1 Like