diff mbox series

REST: don't 500 if we get a non-int ID in /comment/ views

Message ID 20210820153258.2191277-1-dja@axtens.net
State Changes Requested
Headers show
Series REST: don't 500 if we get a non-int ID in /comment/ views | expand

Commit Message

Daniel Axtens Aug. 20, 2021, 3:32 p.m. UTC
The Patch and Cover comment views passed unsanitised patch_id/pk
down to the query set filter, which attempts to convert them to
integers, fails, and propagates a ValueError up to us.

Rather than propagating it to the user as a 500, catch it explicitly
and return a 404. Ideally we'd like to return a 400 and some explanation,
but I can't see an easy way to bend Django or DRF to my will here.

Signed-off-by: Daniel Axtens <dja@axtens.net>

---

Will need some tweaking for 2.2, but conceptually simple.

Stephen, would be interested if you can come up with a better way
to propagate a meaningful error out to the user!
---
 patchwork/api/comment.py | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

Comments

Stephen Finucane Aug. 20, 2021, 10:03 p.m. UTC | #1
On Sat, 2021-08-21 at 01:32 +1000, Daniel Axtens wrote:
> The Patch and Cover comment views passed unsanitised patch_id/pk
> down to the query set filter, which attempts to convert them to
> integers, fails, and propagates a ValueError up to us.
> 
> Rather than propagating it to the user as a 500, catch it explicitly
> and return a 404. Ideally we'd like to return a 400 and some explanation,
> but I can't see an easy way to bend Django or DRF to my will here.
> 
> Signed-off-by: Daniel Axtens <dja@axtens.net>
> 
> ---
> 
> Will need some tweaking for 2.2, but conceptually simple.
> 
> Stephen, would be interested if you can come up with a better way
> to propagate a meaningful error out to the user!

I did indeed find another way to do this. Two ways, in fact. I've submitted a
patch to do both, but tl;dr:

   A. We can use path converters (of type 'int') to ensure these requests never
      even hit our handlers
   B. We can use 'rest_framework.generic.get_object_or_404' instead of Django's
      own implementation, since the former also handles TypeErrors

Let me know if this works for you. I can apply it and cut a new release early
next week if you can't.

Cheers,
Stephen
diff mbox series

Patch

diff --git a/patchwork/api/comment.py b/patchwork/api/comment.py
index 0c578b44f1cb..4fa48ff73e49 100644
--- a/patchwork/api/comment.py
+++ b/patchwork/api/comment.py
@@ -86,6 +86,13 @@  class CoverCommentList(ListAPIView):
     lookup_url_kwarg = 'pk'
 
     def get_queryset(self):
+        # ideally we'd want to raise a 400 here with some explanation, but
+        # it's not clear how to. DRF throws away any 404 message we provide
+        try:
+            int(self.kwargs['pk'])
+        except ValueError:
+            raise Http404
+
         if not Cover.objects.filter(pk=self.kwargs['pk']).exists():
             raise Http404
 
@@ -105,6 +112,13 @@  class PatchCommentList(ListAPIView):
     lookup_url_kwarg = 'patch_id'
 
     def get_queryset(self):
+        # ideally we'd want to raise a 400 here with some explanation, but
+        # it's not clear how to. DRF throws away any 404 message we provide
+        try:
+            int(self.kwargs['patch_id'])
+        except ValueError:
+            raise Http404
+
         if not Patch.objects.filter(id=self.kwargs['patch_id']).exists():
             raise Http404