Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set the headers of multipart/form-data parts with django.test.Client?

Each part in a multipart/form-data document can have its own headers, e.g. a section can have a header Content-Type: text/plain. These parts can be uploaded files from a web form, for example.

In the documentation for Django's UploadedFile class, I read

UploadedFile.content_type

The content-type header uploaded with the file (e.g. text/plain or application/pdf). Like any data supplied by the user, you shouldn’t trust that the uploaded file is actually this type. You’ll still need to validate that the file contains the content that the content-type header claims – “trust but verify.”

Okay, I should validate the file against the claimed content type. So of course, now I need to write some tests which test whether my server actually does validate the content type correctly. One such test would be to make a request to my server with content-type: multipart/form-data, where at least one part has content which is inconsistent with its content-type.

How can I do this? The django.test.Client class has a post method which can send requests with type multipart/form-data. The multiple parts of the request body are passed to the method as a dictionary. The keys of this dictionary are strings, and the values are either strings or "file objects".

I wish to understand:

  1. how this dictionary is converted to a multipart/form-data request body. What are the headers on each part?
  2. how to manually set arbitrary headers on each part. How, for instance, can I manually specify a header Content-Type: text/plain?
like image 455
jameshfisher Avatar asked Mar 23 '15 15:03

jameshfisher


2 Answers

  1. The Django test suite claims it'll always use an application/octet-stream header for files. That's not actually true though, as the encode_file function used actually tries to guess the actual mimetype of the file.
  2. This leads to an answer to your second question: before trying to guess the mimetype, the function looks for a content_type attribute on the file. You should be able to set this to whatever you like and thus overwrite the Content-Type.
like image 84
Martijn Arts Avatar answered Oct 04 '22 05:10

Martijn Arts


The Client class inherits from django.test.client.RequestFactory (src) and effectively and you can see in the Client's post definition that it's basically a call to super, so you can refer to the RequestFactory post definition. By default, this in turn calls _encode_data which uses encode_multipart, which, as you've noticed, specifies "multipart/form-data".

Here, you can see some headers are specified for each part (e.g, Content-Disposition), however I do not see a way to specify a Content-Type header (or any specific header) for each part.

like image 26
Joseph Avatar answered Oct 04 '22 07:10

Joseph