faust icon indicating copy to clipboard operation
faust copied to clipboard

Custom headers are not handled properly when self.error is used in web views

Open popadi opened this issue 2 years ago • 2 comments

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

popadi avatar May 23 '22 13:05 popadi

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)

popadi avatar May 23 '22 13:05 popadi

please open a PR

patkivikram avatar Jun 13 '22 13:06 patkivikram