faust
faust copied to clipboard
Custom headers are not handled properly when self.error is used in web views
Checklist
- [x] I have included information about relevant versions
- [x] I have verified that the issue persists when using the
master
branch of Faust.
Steps to reproduce
If you have a view and you return an error using self.error
, you cannot send extra custom headers. Any other argument besides reason
and status
are merged together in the response, so in the snipped below, the cors_headers
are actually returned to the user, in the response. Using self.json
yields the correct behaviour.
cors_headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Headers': '*',
}
@app.page('/test')
async def test(self, request):
return self.error(reason='test reason', status=400, headers=cors_headers)
Expected behavior
To be able to send custom headers when using self.error
. This helps in the case of UIs that are making web requests to a faust app running somewhere.
Actual behavior
If you have a view and you return an error using self.error
, you cannot send extra custom headers. Any other argument besides reason
and status
are merged together in the response, so in the snipped below, the cors_headers
are actually returned to the user, in the response. Using self.json
yields the correct behaviour.
A way to "bypass" using self.error
is to use self.json
and to build the error message yourself. I think this is caused due to how the method is implemented:
def error(self, status: int, reason: str, **kwargs: Any) -> Response:
"""Create error JSON response."""
return self.json({"error": reason, **kwargs}, status=status)
I'm not entirely sure if **kwargs
is supposed to be in the message or not. I think the headers should be extracted from the kwargs
(if existing) and passed down to self.json
.
I can make a PR with a solution. Let me know what do you think it would be the best solution and I can try and fix it.
Full traceback
No traceback.
Versions
- Python version: 0.7.7
- Faust version: 3.7
- Operating system: Red Had 7
Note that a simple solution would be to have
def error(self, status: int, reason: str, **kwargs: Any) -> Response:
"""Create error JSON response."""
headers = kwargs.pop('headers', {})
return self.json({"error": reason, **kwargs}, status=status, headers=headers)
please open a PR