Python: Model rest_framework.exceptions.APIException

This commit is contained in:
Rasmus Wriedt Larsen
2021-11-12 11:37:54 +01:00
parent 62e58b534c
commit 5e4b866f2b
4 changed files with 71 additions and 0 deletions

View File

@@ -299,4 +299,51 @@ private module RestFramework {
override string getMimetypeDefault() { none() }
}
}
// ---------------------------------------------------------------------------
// Exception response modeling
// ---------------------------------------------------------------------------
/**
* Provides models for the `rest_framework.exceptions.APIException` class and subclasses
*
* See https://www.django-rest-framework.org/api-guide/exceptions/#api-reference
*/
module APIException {
/** A direct instantiation of `rest_framework.exceptions.APIException` or subclass. */
private class ClassInstantiation extends HTTP::Server::HttpResponse::Range,
DataFlow::CallCfgNode {
string className;
ClassInstantiation() {
className in [
"APIException", "ValidationError", "ParseError", "AuthenticationFailed",
"NotAuthenticated", "PermissionDenied", "NotFound", "MethodNotAllowed", "NotAcceptable",
"UnsupportedMediaType", "Throttled"
] and
this =
API::moduleImport("rest_framework")
.getMember("exceptions")
.getMember(className)
.getACall()
}
override DataFlow::Node getBody() {
className in [
"APIException", "ValidationError", "ParseError", "AuthenticationFailed",
"NotAuthenticated", "PermissionDenied", "NotFound", "NotAcceptable"
] and
result = this.getArg(0)
or
className in ["MethodNotAllowed", "UnsupportedMediaType", "Throttled"] and
result = this.getArg(1)
or
result = this.getArgByName("detail")
}
// How to support the `headers` argument here?
override DataFlow::Node getMimetypeOrContentTypeArg() { none() }
override string getMimetypeDefault() { none() }
}
}
}

View File

@@ -1,5 +1,6 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.exceptions import APIException
@api_view()
def normal_response(request): # $ requestHandler
@@ -32,3 +33,18 @@ def setting_cookie(request):
resp.delete_cookie("key4") # $ CookieWrite CookieName="key4"
resp.delete_cookie(key="key4") # $ CookieWrite CookieName="key4"
return resp
################################################################################
# Exceptions
################################################################################
# see https://www.django-rest-framework.org/api-guide/exceptions/
@api_view(["GET", "POST"])
def exception_test(request): # $ requestHandler
data = "exception details"
# note: `code details` not exposed by default
code = "code details"
e1 = APIException(data, code) # $ HttpResponse responseBody=data
e2 = APIException(detail=data, code=code) # $ HttpResponse responseBody=data
raise e2

View File

@@ -14,4 +14,5 @@ urlpatterns = [
path("class-based-view/", views.MyClass.as_view()), # $routeSetup="lcass-based-view/"
path("function-based-view/", views.function_based_view), # $routeSetup="function-based-view/"
path("cookie-test/", views.cookie_test), # $routeSetup="function-based-view/"
path("exception-test/", views.exception_test), # $routeSetup="exception-test/"
]

View File

@@ -6,6 +6,7 @@ from rest_framework.decorators import api_view
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.exceptions import APIException
# Viewsets
# see https://www.django-rest-framework.org/tutorial/quickstart/
@@ -50,3 +51,9 @@ def cookie_test(request: Request):
resp.headers["Set-Cookie"] = "key2=value2" # $ MISSING: CookieWrite CookieRawHeader="key2=value2"
resp.cookies["key3"] = "value3" # $ CookieWrite CookieName="key3" CookieValue="value3"
return resp
@api_view(["GET", "POST"])
def exception_test(request: Request):
# see https://www.django-rest-framework.org/api-guide/exceptions/
# note: `code details` not exposed by default
raise APIException("exception details", "code details")