Merge pull request #14353 from GeekMasher/py-restframework

Python: support `*args` and `**kwargs` in request handlers
This commit is contained in:
Rasmus Wriedt Larsen
2023-11-23 14:04:36 +01:00
committed by GitHub
9 changed files with 128 additions and 15 deletions

View File

@@ -150,3 +150,40 @@ class UnknownViewSubclass(UnknownViewSuperclass):
urlpatterns = [
path("UnknownViewSubclass/", UnknownViewSubclass.as_view()), # $ routeSetup="UnknownViewSubclass/"
]
################################################################################
# Routing to *args and **kwargs
################################################################################
def kwargs_param(request, **kwargs): # $ requestHandler routedParameter=kwargs
ensure_tainted(
kwargs, # $ tainted
kwargs["foo"], # $ tainted
kwargs["bar"] # $ tainted
)
ensure_tainted(request) # $ tainted
def star_args_param(request, *args): # $ requestHandler routedParameter=args
ensure_tainted(
args, # $ tainted
args[0], # $ tainted
args[1], # $ tainted
)
ensure_tainted(request) # $ tainted
def star_args_param_check(request, foo, bar): # $ requestHandler routedParameter=foo routedParameter=bar
ensure_tainted(
foo, # $ tainted
bar, # $ tainted
)
ensure_tainted(request) # $ tainted
urlpatterns = [
path("test-kwargs_param/<foo>/<bar>", kwargs_param), # $ routeSetup="test-kwargs_param/<foo>/<bar>"
re_path("test-star_args_param/([^/]+)/(.+)", star_args_param), # $ routeSetup="test-star_args_param/([^/]+)/(.+)"
re_path("test-star_args_param_check/([^/]+)/(.+)", star_args_param_check), # $ routeSetup="test-star_args_param_check/([^/]+)/(.+)"
]

View File

@@ -1,5 +1,6 @@
from rest_framework.decorators import api_view, parser_classes
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.parsers import JSONParser
@@ -89,7 +90,7 @@ def test_taint(request: Request, routed_param): # $ requestHandler routedParamet
class MyClass(APIView):
def initial(self, request, *args, **kwargs): # $ requestHandler
def initial(self, request, *args, **kwargs): # $ requestHandler routedParameter=kwargs
# this method will be called before processing any request
ensure_tainted(request) # $ tainted
@@ -107,12 +108,31 @@ class MyClass(APIView):
return Response("ok") # $ HttpResponse
# Viewsets
# see https://www.django-rest-framework.org/api-guide/viewsets/
class MyModelViewSet(ModelViewSet):
def retrieve(self, request, routed_param): # $ requestHandler routedParameter=routed_param
ensure_tainted(
request, # $ tainted
request.GET, # $ tainted
request.GET.get("pk"), # $ tainted
request.data # $ tainted
)
ensure_tainted(routed_param) # $ tainted
# same as for standard Django view
ensure_tainted(self.args, self.kwargs) # $ tainted
return Response("retrieve") # $ HttpResponse
# fake setup, you can't actually run this
urlpatterns = [
path("test-taint/<routed_param>", test_taint), # $ routeSetup="test-taint/<routed_param>"
path("ClassView/<routed_param>", MyClass.as_view()), # $ routeSetup="ClassView/<routed_param>"
path("MyModelViewSet/<routed_param>", MyModelViewSet.as_view()) # $ routeSetup="MyModelViewSet/<routed_param>"
]
# tests with no route-setup, but we can still tell that these are using Django REST