Skip to content

Commit 76280b4

Browse files
smithdc1felixxm
authored andcommitted
Refs #21442 -- Increased test coverage of requests.
1 parent baf705f commit 76280b4

File tree

1 file changed

+271
-0
lines changed

1 file changed

+271
-0
lines changed

tests/requests_tests/tests.py

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from urllib.parse import urlencode
55

66
from django.core.exceptions import BadRequest, DisallowedHost
7+
from django.core.files.uploadedfile import InMemoryUploadedFile
8+
from django.core.files.uploadhandler import MemoryFileUploadHandler
79
from django.core.handlers.wsgi import LimitedStream, WSGIRequest
810
from django.http import (
911
HttpHeaders,
@@ -17,6 +19,20 @@
1719
from django.test.client import BOUNDARY, MULTIPART_CONTENT, FakePayload
1820

1921

22+
class ErrorFileUploadHandler(MemoryFileUploadHandler):
23+
def handle_raw_input(
24+
self, input_data, META, content_length, boundary, encoding=None
25+
):
26+
raise ValueError
27+
28+
29+
class CustomFileUploadHandler(MemoryFileUploadHandler):
30+
def handle_raw_input(
31+
self, input_data, META, content_length, boundary, encoding=None
32+
):
33+
return ("_POST", "_FILES")
34+
35+
2036
class RequestsTests(SimpleTestCase):
2137
def test_httprequest(self):
2238
request = HttpRequest()
@@ -491,6 +507,261 @@ def test_POST_multipart_with_content_length_zero(self):
491507
)
492508
self.assertEqual(request.POST, {})
493509

510+
@override_settings(
511+
FILE_UPLOAD_HANDLERS=["requests_tests.tests.ErrorFileUploadHandler"]
512+
)
513+
def test_POST_multipart_handler_error(self):
514+
payload = FakePayload(
515+
"\r\n".join(
516+
[
517+
f"--{BOUNDARY}",
518+
'Content-Disposition: form-data; name="name"',
519+
"",
520+
"value",
521+
f"--{BOUNDARY}--",
522+
]
523+
)
524+
)
525+
request = WSGIRequest(
526+
{
527+
"REQUEST_METHOD": "POST",
528+
"CONTENT_TYPE": MULTIPART_CONTENT,
529+
"CONTENT_LENGTH": len(payload),
530+
"wsgi.input": payload,
531+
}
532+
)
533+
with self.assertRaises(ValueError):
534+
request.POST
535+
536+
@override_settings(
537+
FILE_UPLOAD_HANDLERS=["requests_tests.tests.CustomFileUploadHandler"]
538+
)
539+
def test_POST_multipart_handler_parses_input(self):
540+
payload = FakePayload(
541+
"\r\n".join(
542+
[
543+
f"--{BOUNDARY}",
544+
'Content-Disposition: form-data; name="name"',
545+
"",
546+
"value",
547+
f"--{BOUNDARY}--",
548+
]
549+
)
550+
)
551+
request = WSGIRequest(
552+
{
553+
"REQUEST_METHOD": "POST",
554+
"CONTENT_TYPE": MULTIPART_CONTENT,
555+
"CONTENT_LENGTH": len(payload),
556+
"wsgi.input": payload,
557+
}
558+
)
559+
self.assertEqual(request.POST, "_POST")
560+
self.assertEqual(request.FILES, "_FILES")
561+
562+
def test_request_methods_with_content(self):
563+
for method in ["GET", "PUT", "DELETE"]:
564+
with self.subTest(method=method):
565+
payload = FakePayload(urlencode({"key": "value"}))
566+
request = WSGIRequest(
567+
{
568+
"REQUEST_METHOD": method,
569+
"CONTENT_LENGTH": len(payload),
570+
"CONTENT_TYPE": "application/x-www-form-urlencoded",
571+
"wsgi.input": payload,
572+
}
573+
)
574+
self.assertEqual(request.POST, {})
575+
576+
def test_POST_content_type_json(self):
577+
payload = FakePayload(
578+
"\r\n".join(
579+
[
580+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly Ha',
581+
'rmless", "author": ["Douglas", Adams"]}}',
582+
]
583+
)
584+
)
585+
request = WSGIRequest(
586+
{
587+
"REQUEST_METHOD": "POST",
588+
"CONTENT_TYPE": "application/json",
589+
"CONTENT_LENGTH": len(payload),
590+
"wsgi.input": payload,
591+
}
592+
)
593+
self.assertEqual(request.POST, {})
594+
self.assertEqual(request.FILES, {})
595+
596+
_json_payload = [
597+
'Content-Disposition: form-data; name="JSON"',
598+
"Content-Type: application/json",
599+
"",
600+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly Harmless", '
601+
'"author": ["Douglas", Adams"]}}',
602+
]
603+
604+
def test_POST_form_data_json(self):
605+
payload = FakePayload(
606+
"\r\n".join([f"--{BOUNDARY}", *self._json_payload, f"--{BOUNDARY}--"])
607+
)
608+
request = WSGIRequest(
609+
{
610+
"REQUEST_METHOD": "POST",
611+
"CONTENT_TYPE": MULTIPART_CONTENT,
612+
"CONTENT_LENGTH": len(payload),
613+
"wsgi.input": payload,
614+
}
615+
)
616+
self.assertEqual(
617+
request.POST,
618+
{
619+
"JSON": [
620+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly '
621+
'Harmless", "author": ["Douglas", Adams"]}}'
622+
],
623+
},
624+
)
625+
626+
def test_POST_multipart_json(self):
627+
payload = FakePayload(
628+
"\r\n".join(
629+
[
630+
f"--{BOUNDARY}",
631+
'Content-Disposition: form-data; name="name"',
632+
"",
633+
"value",
634+
f"--{BOUNDARY}",
635+
*self._json_payload,
636+
f"--{BOUNDARY}--",
637+
]
638+
)
639+
)
640+
request = WSGIRequest(
641+
{
642+
"REQUEST_METHOD": "POST",
643+
"CONTENT_TYPE": MULTIPART_CONTENT,
644+
"CONTENT_LENGTH": len(payload),
645+
"wsgi.input": payload,
646+
}
647+
)
648+
self.assertEqual(
649+
request.POST,
650+
{
651+
"name": ["value"],
652+
"JSON": [
653+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly '
654+
'Harmless", "author": ["Douglas", Adams"]}}'
655+
],
656+
},
657+
)
658+
659+
def test_POST_multipart_json_csv(self):
660+
payload = FakePayload(
661+
"\r\n".join(
662+
[
663+
f"--{BOUNDARY}",
664+
'Content-Disposition: form-data; name="name"',
665+
"",
666+
"value",
667+
f"--{BOUNDARY}",
668+
*self._json_payload,
669+
f"--{BOUNDARY}",
670+
'Content-Disposition: form-data; name="CSV"',
671+
"Content-Type: text/csv",
672+
"",
673+
"Framework,ID.Django,1.Flask,2.",
674+
f"--{BOUNDARY}--",
675+
]
676+
)
677+
)
678+
request = WSGIRequest(
679+
{
680+
"REQUEST_METHOD": "POST",
681+
"CONTENT_TYPE": MULTIPART_CONTENT,
682+
"CONTENT_LENGTH": len(payload),
683+
"wsgi.input": payload,
684+
}
685+
)
686+
self.assertEqual(
687+
request.POST,
688+
{
689+
"name": ["value"],
690+
"JSON": [
691+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly '
692+
'Harmless", "author": ["Douglas", Adams"]}}'
693+
],
694+
"CSV": ["Framework,ID.Django,1.Flask,2."],
695+
},
696+
)
697+
698+
def test_POST_multipart_with_file(self):
699+
payload = FakePayload(
700+
"\r\n".join(
701+
[
702+
f"--{BOUNDARY}",
703+
'Content-Disposition: form-data; name="name"',
704+
"",
705+
"value",
706+
f"--{BOUNDARY}",
707+
*self._json_payload,
708+
f"--{BOUNDARY}",
709+
'Content-Disposition: form-data; name="File"; filename="test.csv"',
710+
"Content-Type: application/octet-stream",
711+
"",
712+
"Framework,ID",
713+
"Django,1",
714+
"Flask,2",
715+
f"--{BOUNDARY}--",
716+
]
717+
)
718+
)
719+
request = WSGIRequest(
720+
{
721+
"REQUEST_METHOD": "POST",
722+
"CONTENT_TYPE": MULTIPART_CONTENT,
723+
"CONTENT_LENGTH": len(payload),
724+
"wsgi.input": payload,
725+
}
726+
)
727+
self.assertEqual(
728+
request.POST,
729+
{
730+
"name": ["value"],
731+
"JSON": [
732+
'{"pk": 1, "model": "store.book", "fields": {"name": "Mostly '
733+
'Harmless", "author": ["Douglas", Adams"]}}'
734+
],
735+
},
736+
)
737+
self.assertEqual(len(request.FILES), 1)
738+
self.assertIsInstance((request.FILES["File"]), InMemoryUploadedFile)
739+
740+
def test_base64_invalid_encoding(self):
741+
payload = FakePayload(
742+
"\r\n".join(
743+
[
744+
f"--{BOUNDARY}",
745+
'Content-Disposition: form-data; name="file"; filename="test.txt"',
746+
"Content-Type: application/octet-stream",
747+
"Content-Transfer-Encoding: base64",
748+
"",
749+
f"\r\nZsg£\r\n--{BOUNDARY}--",
750+
]
751+
)
752+
)
753+
request = WSGIRequest(
754+
{
755+
"REQUEST_METHOD": "POST",
756+
"CONTENT_TYPE": MULTIPART_CONTENT,
757+
"CONTENT_LENGTH": len(payload),
758+
"wsgi.input": payload,
759+
}
760+
)
761+
msg = "Could not decode base64 data."
762+
with self.assertRaisesMessage(MultiPartParserError, msg):
763+
request.POST
764+
494765
def test_POST_binary_only(self):
495766
payload = b"\r\n\x01\x00\x00\x00ab\x00\x00\xcd\xcc,@"
496767
environ = {

0 commit comments

Comments
 (0)