1. from io import BytesIO
    
  2. 
    
  3. from django.core.exceptions import (
    
  4.     RequestDataTooBig,
    
  5.     TooManyFieldsSent,
    
  6.     TooManyFilesSent,
    
  7. )
    
  8. from django.core.handlers.wsgi import WSGIRequest
    
  9. from django.test import SimpleTestCase
    
  10. from django.test.client import FakePayload
    
  11. 
    
  12. TOO_MANY_FIELDS_MSG = (
    
  13.     "The number of GET/POST parameters exceeded settings.DATA_UPLOAD_MAX_NUMBER_FIELDS."
    
  14. )
    
  15. TOO_MANY_FILES_MSG = (
    
  16.     "The number of files exceeded settings.DATA_UPLOAD_MAX_NUMBER_FILES."
    
  17. )
    
  18. TOO_MUCH_DATA_MSG = "Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE."
    
  19. 
    
  20. 
    
  21. class DataUploadMaxMemorySizeFormPostTests(SimpleTestCase):
    
  22.     def setUp(self):
    
  23.         payload = FakePayload("a=1&a=2&a=3\r\n")
    
  24.         self.request = WSGIRequest(
    
  25.             {
    
  26.                 "REQUEST_METHOD": "POST",
    
  27.                 "CONTENT_TYPE": "application/x-www-form-urlencoded",
    
  28.                 "CONTENT_LENGTH": len(payload),
    
  29.                 "wsgi.input": payload,
    
  30.             }
    
  31.         )
    
  32. 
    
  33.     def test_size_exceeded(self):
    
  34.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=12):
    
  35.             with self.assertRaisesMessage(RequestDataTooBig, TOO_MUCH_DATA_MSG):
    
  36.                 self.request._load_post_and_files()
    
  37. 
    
  38.     def test_size_not_exceeded(self):
    
  39.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=13):
    
  40.             self.request._load_post_and_files()
    
  41. 
    
  42.     def test_no_limit(self):
    
  43.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=None):
    
  44.             self.request._load_post_and_files()
    
  45. 
    
  46. 
    
  47. class DataUploadMaxMemorySizeMultipartPostTests(SimpleTestCase):
    
  48.     def setUp(self):
    
  49.         payload = FakePayload(
    
  50.             "\r\n".join(
    
  51.                 [
    
  52.                     "--boundary",
    
  53.                     'Content-Disposition: form-data; name="name"',
    
  54.                     "",
    
  55.                     "value",
    
  56.                     "--boundary--",
    
  57.                 ]
    
  58.             )
    
  59.         )
    
  60.         self.request = WSGIRequest(
    
  61.             {
    
  62.                 "REQUEST_METHOD": "POST",
    
  63.                 "CONTENT_TYPE": "multipart/form-data; boundary=boundary",
    
  64.                 "CONTENT_LENGTH": len(payload),
    
  65.                 "wsgi.input": payload,
    
  66.             }
    
  67.         )
    
  68. 
    
  69.     def test_size_exceeded(self):
    
  70.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=10):
    
  71.             with self.assertRaisesMessage(RequestDataTooBig, TOO_MUCH_DATA_MSG):
    
  72.                 self.request._load_post_and_files()
    
  73. 
    
  74.     def test_size_not_exceeded(self):
    
  75.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=11):
    
  76.             self.request._load_post_and_files()
    
  77. 
    
  78.     def test_no_limit(self):
    
  79.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=None):
    
  80.             self.request._load_post_and_files()
    
  81. 
    
  82.     def test_file_passes(self):
    
  83.         payload = FakePayload(
    
  84.             "\r\n".join(
    
  85.                 [
    
  86.                     "--boundary",
    
  87.                     'Content-Disposition: form-data; name="file1"; '
    
  88.                     'filename="test.file"',
    
  89.                     "",
    
  90.                     "value",
    
  91.                     "--boundary--",
    
  92.                 ]
    
  93.             )
    
  94.         )
    
  95.         request = WSGIRequest(
    
  96.             {
    
  97.                 "REQUEST_METHOD": "POST",
    
  98.                 "CONTENT_TYPE": "multipart/form-data; boundary=boundary",
    
  99.                 "CONTENT_LENGTH": len(payload),
    
  100.                 "wsgi.input": payload,
    
  101.             }
    
  102.         )
    
  103.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=1):
    
  104.             request._load_post_and_files()
    
  105.             self.assertIn("file1", request.FILES, "Upload file not present")
    
  106. 
    
  107. 
    
  108. class DataUploadMaxMemorySizeGetTests(SimpleTestCase):
    
  109.     def setUp(self):
    
  110.         self.request = WSGIRequest(
    
  111.             {
    
  112.                 "REQUEST_METHOD": "GET",
    
  113.                 "wsgi.input": BytesIO(b""),
    
  114.                 "CONTENT_LENGTH": 3,
    
  115.             }
    
  116.         )
    
  117. 
    
  118.     def test_data_upload_max_memory_size_exceeded(self):
    
  119.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=2):
    
  120.             with self.assertRaisesMessage(RequestDataTooBig, TOO_MUCH_DATA_MSG):
    
  121.                 self.request.body
    
  122. 
    
  123.     def test_size_not_exceeded(self):
    
  124.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=3):
    
  125.             self.request.body
    
  126. 
    
  127.     def test_no_limit(self):
    
  128.         with self.settings(DATA_UPLOAD_MAX_MEMORY_SIZE=None):
    
  129.             self.request.body
    
  130. 
    
  131.     def test_empty_content_length(self):
    
  132.         self.request.environ["CONTENT_LENGTH"] = ""
    
  133.         self.request.body
    
  134. 
    
  135. 
    
  136. class DataUploadMaxNumberOfFieldsGet(SimpleTestCase):
    
  137.     def test_get_max_fields_exceeded(self):
    
  138.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=1):
    
  139.             with self.assertRaisesMessage(TooManyFieldsSent, TOO_MANY_FIELDS_MSG):
    
  140.                 request = WSGIRequest(
    
  141.                     {
    
  142.                         "REQUEST_METHOD": "GET",
    
  143.                         "wsgi.input": BytesIO(b""),
    
  144.                         "QUERY_STRING": "a=1&a=2&a=3",
    
  145.                     }
    
  146.                 )
    
  147.                 request.GET["a"]
    
  148. 
    
  149.     def test_get_max_fields_not_exceeded(self):
    
  150.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=3):
    
  151.             request = WSGIRequest(
    
  152.                 {
    
  153.                     "REQUEST_METHOD": "GET",
    
  154.                     "wsgi.input": BytesIO(b""),
    
  155.                     "QUERY_STRING": "a=1&a=2&a=3",
    
  156.                 }
    
  157.             )
    
  158.             request.GET["a"]
    
  159. 
    
  160. 
    
  161. class DataUploadMaxNumberOfFieldsMultipartPost(SimpleTestCase):
    
  162.     def setUp(self):
    
  163.         payload = FakePayload(
    
  164.             "\r\n".join(
    
  165.                 [
    
  166.                     "--boundary",
    
  167.                     'Content-Disposition: form-data; name="name1"',
    
  168.                     "",
    
  169.                     "value1",
    
  170.                     "--boundary",
    
  171.                     'Content-Disposition: form-data; name="name2"',
    
  172.                     "",
    
  173.                     "value2",
    
  174.                     "--boundary--",
    
  175.                 ]
    
  176.             )
    
  177.         )
    
  178.         self.request = WSGIRequest(
    
  179.             {
    
  180.                 "REQUEST_METHOD": "POST",
    
  181.                 "CONTENT_TYPE": "multipart/form-data; boundary=boundary",
    
  182.                 "CONTENT_LENGTH": len(payload),
    
  183.                 "wsgi.input": payload,
    
  184.             }
    
  185.         )
    
  186. 
    
  187.     def test_number_exceeded(self):
    
  188.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=1):
    
  189.             with self.assertRaisesMessage(TooManyFieldsSent, TOO_MANY_FIELDS_MSG):
    
  190.                 self.request._load_post_and_files()
    
  191. 
    
  192.     def test_number_not_exceeded(self):
    
  193.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=2):
    
  194.             self.request._load_post_and_files()
    
  195. 
    
  196.     def test_no_limit(self):
    
  197.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=None):
    
  198.             self.request._load_post_and_files()
    
  199. 
    
  200. 
    
  201. class DataUploadMaxNumberOfFilesMultipartPost(SimpleTestCase):
    
  202.     def setUp(self):
    
  203.         payload = FakePayload(
    
  204.             "\r\n".join(
    
  205.                 [
    
  206.                     "--boundary",
    
  207.                     (
    
  208.                         'Content-Disposition: form-data; name="name1"; '
    
  209.                         'filename="name1.txt"'
    
  210.                     ),
    
  211.                     "",
    
  212.                     "value1",
    
  213.                     "--boundary",
    
  214.                     (
    
  215.                         'Content-Disposition: form-data; name="name2"; '
    
  216.                         'filename="name2.txt"'
    
  217.                     ),
    
  218.                     "",
    
  219.                     "value2",
    
  220.                     "--boundary--",
    
  221.                 ]
    
  222.             )
    
  223.         )
    
  224.         self.request = WSGIRequest(
    
  225.             {
    
  226.                 "REQUEST_METHOD": "POST",
    
  227.                 "CONTENT_TYPE": "multipart/form-data; boundary=boundary",
    
  228.                 "CONTENT_LENGTH": len(payload),
    
  229.                 "wsgi.input": payload,
    
  230.             }
    
  231.         )
    
  232. 
    
  233.     def test_number_exceeded(self):
    
  234.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FILES=1):
    
  235.             with self.assertRaisesMessage(TooManyFilesSent, TOO_MANY_FILES_MSG):
    
  236.                 self.request._load_post_and_files()
    
  237. 
    
  238.     def test_number_not_exceeded(self):
    
  239.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FILES=2):
    
  240.             self.request._load_post_and_files()
    
  241. 
    
  242.     def test_no_limit(self):
    
  243.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FILES=None):
    
  244.             self.request._load_post_and_files()
    
  245. 
    
  246. 
    
  247. class DataUploadMaxNumberOfFieldsFormPost(SimpleTestCase):
    
  248.     def setUp(self):
    
  249.         payload = FakePayload("\r\n".join(["a=1&a=2&a=3", ""]))
    
  250.         self.request = WSGIRequest(
    
  251.             {
    
  252.                 "REQUEST_METHOD": "POST",
    
  253.                 "CONTENT_TYPE": "application/x-www-form-urlencoded",
    
  254.                 "CONTENT_LENGTH": len(payload),
    
  255.                 "wsgi.input": payload,
    
  256.             }
    
  257.         )
    
  258. 
    
  259.     def test_number_exceeded(self):
    
  260.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=2):
    
  261.             with self.assertRaisesMessage(TooManyFieldsSent, TOO_MANY_FIELDS_MSG):
    
  262.                 self.request._load_post_and_files()
    
  263. 
    
  264.     def test_number_not_exceeded(self):
    
  265.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=3):
    
  266.             self.request._load_post_and_files()
    
  267. 
    
  268.     def test_no_limit(self):
    
  269.         with self.settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=None):
    
  270.             self.request._load_post_and_files()