If I abort a request with a 404, I get a traceback in the server log. Is that by design?
import sys,os
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
from sanic import Sanic
from sanic.exceptions import abort
from sanic.response import text
if __name__ == "__main__":
app = Sanic()
@app.route('/foo')
async def test(request):
abort(404)
@app.route('/')
async def root(request):
return text('hi')
app.run(host=app.config.get('HOST', '0.0.0.0'),
port=app.config.get('PORT', 8000),
debug=app.config.get('DEBUG', True))
Running that server and doing a GET /foo shows this in the log:
2018-08-31 11:39:03 -0400] [38369] [ERROR] Traceback (most recent call last):
File "...sanic/app.py", line 603, in handle_request
response = await response
File "...lib/python3.6/asyncio/coroutines.py", line 110, in __next__
return self.gen.send(None)
File "server.py", line 21, in test
abort(404)
File "sanic/exceptions.py", line 288, in abort
raise sanic_exception(message=message, status_code=status_code)
sanic.exceptions.NotFound: Not Found
[2018-08-31 11:39:03 -0400] - (sanic.access)[INFO][127.0.0.1:52586]: GET http://localhost:8000/foo 404 16
I'd rather just see the access 404 log line.
That is sanics default behavior for all exceptions.
You need to override how sanic handles that exception:
@app.exception(NotFound)
def ignore_404s(request, exception):
return text("Yep, I totally found the page: {}".format(request.url))
Well, I still want to return a 404. Would that do it, or would it return valid text?
I guess I can do return text('not found', status=404) though.
Just seems to me like a stack trace in the log is excessive for a 404 -- websites are constantly getting probed by hackers, so that just makes a lot of noise in the logs, and it's not like you need the stack trace to see what went wrong.
But the workaround is OK for me, so this issue can be closed if this is working as intended.
return response.HTTPResponse(status=404)
This just returns 404 without any body
I think that is a good point, a traceback is overkill for a 404 unless maybe if debug mode is enabled.
I'm not sure I agree. I think it points to something that ought to be considered a "best" practice, and that is creating an exception handler as @TheGrandmother pointed out. A basic example is in the docs.
I do something similar, but explicitly tell it to return 404 status.
@app.exception(NotFound)
def page_not_found(request, exception):
return text("Page not found: {}".format(request.path), status=404)
I think that having it raise an exception makes sense as NotFound is then a subclass of SanicException.
What would the alternative be? Creating a premade handler? I think part of the usefulness of sanic is that it does not pre-make decisions like this for you.
That's what I ended up doing. But only after my logs started filling up due to bots knocking on the door all the time.
I think that maybe we should add a section to the documentation with a "checklist" of things to be on the look out for pre-deployment, this being one of them.
Most helpful comment
Well, I still want to return a 404. Would that do it, or would it return valid text?
I guess I can do
return text('not found', status=404)though.Just seems to me like a stack trace in the log is excessive for a 404 -- websites are constantly getting probed by hackers, so that just makes a lot of noise in the logs, and it's not like you need the stack trace to see what went wrong.
But the workaround is OK for me, so this issue can be closed if this is working as intended.