Why WSGIRequest attribute "body" contains “\n” in place of newline?

Noticed after upgrading to Python3.7 + Django3.1, in attribute _request.body , newline was converted to two characters of "\n" . PyCharm hint shows that _request is an object in class of WSGIRequest . As the partial log shows below, the text record contains “\n” in place of the newline.

I suspect this is related to encoding of the new version of Python, and the issue doesn’t exist in Python2.7 + Django1.11. Any pointers will be highly appreciated.

Partial logs:

[09/Dec/2020 08:22:37] INFO [application.soap.views:34] b'<?xml version="1.0" encoding="UTF-8"?>\n<env:Envelope ... >...</env:Envelope>\n'
[09/Dec/2020 08:22:37] INFO [application.soap.views:28] <HttpResponse status_code=200, "application/soap+xml">

Notice the portion of ...encoding="UTF-8"?>\n... and ...</env:Envelope>\n .

More details of source code:

>>> in file main_url.py:

urlpatterns = [
    url(r'^validation/
```, soap_views.receive_validation_request, name='validation_request'),
...

>>> in file view.py:

def receive_validation_request(request):
    (product_valid, common_fields, custom_fields, ecommerce_fields) = validate_request(request, False)
    ...

def validate_request(_request, is_fulfillment=False):
    ...
    logger.info(_request.body)
...

That’s what’s showing in your logs - what’s the actual data?
(If you print _request.body, what do you get?)

Yes there is a difference between Python 2.7 and Python 3.x in that there’s a distinction made between bytes (b'...') and character strings ('...'). What you’re seeing in your log is the representation of the bytes object.

The data you get from an http request is going to be a bytes object. If it is xml, you’re probably going to want to convert it to a string before processing.

See https://docs.python.org/3/howto/unicode.html, https://docs.python.org/3/library/stdtypes.html#string-methods, and https://docs.python.org/3/library/stdtypes.html#binary-sequence-types-bytes-bytearray-memoryview.

(If you’re converting from Python 2.x to 3.x, you’ll probably want to review all the differences between them.)

2 Likes

Thank you for your help, @KenWhitesell.

I resolved the issue by _request.body.decode("utf-8"), and print(_request.body) displays message begin with b so it’s in bytes.