I wrote middleware to catch requests and view them on admin page. It successfully views raw text request body, but fails on image render.
admin.py
class RequestLogEntryAdmin(admin.ModelAdmin):
fieldsets = (
('Request', {
'fields': ('request_headers', 'request_size', 'request_body_'),
})
)
def request_body_(self, obj):
if b'Content-Type: image/png' in base64.b64decode(obj.request_body):
return obj.image_handler(bytes(obj.request_body))
return bytes(obj.request_body)
models.py
class RequestLogEntry(models.Model):
# ...
request_body = models.BinaryField(null=True)
# ...
def image_handler(self, binaryfield):
return mark_safe(f'<img src="data:image/png;base64,{binaryfield}" width="150" height="150" />')
Before saving request.body is being base64 encoded
middleware.py
# ...
log_entry.request_body = base64.b64encode(request.body)
# ...
Current code produces the following:
Base64 decoded request.body looks like this:
My guess is that some extra data being mixed with the image bytes (like 'Content-Disposition' and 'Content-Type' headers), but I'm not sure how can I cut it out from the request body.
When you encode the HttpRequest.body
like so:
base64.b64encode(request.body)
You are actually encoding the raw HTTP request body (which is a bytestring
) as a Base64 [wikipedia.org] encoded string.
HTTP is a text based protocol. The body and the headers are represented as a sequence of characters. Django reserves this feature of HTTP by keeping the raw body in HttpRequest.body
for anyone who wants to work at this low level.
But since the request contains files, you should handle it this way:
if request.FILES:
file = request.FILES.get("image")
if file:
log_entry.request_body = file.read() #[1]
Now image_handler()
will have to change a little because binaryfield
is raw bits of binary data and not Base64 string.
def image_handler(self, binaryfield):
return mark_safe(f"<img src='data:image/png;base64,{base64.b64encode(binaryfield)}' width='150' height='150' />")
[1] Upon calling read()
on an UploadedFile
, you are essentially reading the entire data from the UploadedFile
into memory. Be careful with this method: if the uploaded file is huge it can overwhelm your system.