Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"No POST data" in error report #7953

Open
3 tasks done
bblanchon opened this issue Apr 27, 2021 · 17 comments
Open
3 tasks done

"No POST data" in error report #7953

bblanchon opened this issue Apr 27, 2021 · 17 comments

Comments

@bblanchon
Copy link

Checklist

Description

I'm using Django 3.1.7 & DRF 3.12.2.
When an exception occurs in a ViewSet, Django automatically sends an email to the administrator.

The problem is that the POST data is always empty in this email:

POST: No POST data

Instead, I expect to see the JSON payload that was sent in the request body.

I added a breakpoint in django.utils.log.AdminEmailHandler.emit(), and I can confirm that request.POST is empty.
But on the other hand, I'm sure that request.data was not empty in the ViewSet.

I verified that the request's Content-Type and X-Requested-With are correctly set.
The only non-standard middlewares I use are corsheaders and admin_reorder; I don't think they are related to this problem.

@danielmoessner
Copy link

Any progress on this issue? I have the same problem.

@Hafnernuss
Copy link

Hafnernuss commented Mar 1, 2022

I can also confirm this issue, and it makes it a little bit hard to trace back errors

Here is a discussion related to this problem

@rvinzent
Copy link

rvinzent commented Apr 8, 2022

At this point I am convinced DRF is a dead project

@stale
Copy link

stale bot commented Jun 12, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 12, 2022
@bblanchon
Copy link
Author

I still think this is an important feature, please don't close this issue.

@stale stale bot removed the stale label Jun 12, 2022
@Hafnernuss
Copy link

I agree.

@markdawson
Copy link

I'm also having this issue.

@stale
Copy link

stale bot commented Oct 1, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 1, 2022
@bblanchon
Copy link
Author

I still think this is an important feature, please don't close this issue.

@stale stale bot removed the stale label Oct 1, 2022
@donghj2000
Copy link

donghj2000 commented Nov 14, 2022

It is because django dose not parse body of application/json to request.POST field.You can convert json string to dict by yourself, like this:
res = request.body
json_str = res.decode('utf-8')
json_dict = json.loads(json_str)
Then write a custom log handler class instead of AdminEmailHandler to send your own dict data converted from json.

@donghj2000
Copy link

donghj2000 commented Nov 14, 2022

some code snippet:

 def emit(self, record):
        try:
            request = record.request
            subject = '%s (%s IP): %s' % (
                record.levelname,
                ('internal' if request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS
                 else 'EXTERNAL'),
                record.getMessage()
            )

            import json
            from django.http import QueryDict
            json_str = request.body.decode('utf-8')
            json_dict = json.loads(json_str)
            query_dict = QueryDict(mutable=True)
            for key in json_dict.keys():
                query_dict[key] = json_dict[key]
            request.POST = query_dict
            
        except Exception as ex:
            subject = '%s: %s' % (
                record.levelname,
                record.getMessage()
            )
            request = None
        subject = self.format_subject(subject)

and the message is ...\n\nGET: No GET data\n\nPOST:\nusername = 'python1'\npassword = '123456'\n\nFILES: No FILES data...

@bblanchon
Copy link
Author

Thanks, @donghj2000, this is awesome, but I still think this should be a built-in feature.

@donghj2000
Copy link

Glad to help you. I have not found why they didn't do so. Another workaround is to use Middleware:

class ParseJsonData(MiddlewareMixin):
    def process_request(self, request):
        if request.content_type.startswith("application/json"):
            try:
                json_str = request.body.decode('utf-8')
                json_dict = json.loads(json_str)
                query_dict = QueryDict(mutable=True)
                for key in json_dict.keys():
                    query_dict[key] = json_dict[key]
                request.POST = query_dict
            except Exception as ex:
                pass

@rvinzent
Copy link

rvinzent commented Nov 17, 2022

Glad to help you. I have not found why they didn't do so. Another workaround is to use Middleware:

class ParseJsonData(MiddlewareMixin):
    def process_request(self, request):
        if request.content_type.startswith("application/json"):
            try:
                json_str = request.body.decode('utf-8')
                json_dict = json.loads(json_str)
                query_dict = QueryDict(mutable=True)
                for key in json_dict.keys():
                    query_dict[key] = json_dict[key]
                request.POST = query_dict
            except Exception as ex:
                pass

This snippet has an issue where it assumes the JSON is an object and will fail on any other valid JSON value

@donghj2000
Copy link

It seems to be a bug exactly, but request.POST is initialized as a QueryDict(django.http.request.py->class HttpRequest) ,so I don't know how to deal with other JSON type...

@auvipy
Copy link
Member

auvipy commented Nov 30, 2022

At this point I am convinced DRF is a dead project

no. it has 4 new more maintainers now. btw would love to see a failing test case to find out the fix for the problem. who is up for that? here is a comment pointing to the direction #1671 (comment)

@jonnythebard
Copy link

@auvipy

would love to see a failing test case to find out the fix for the problem

I can do this but I'd like to know the definition of the problem from your side.

@donghj2000 said,

It is because django dose not parse body of application/json to request.POST field.

Do you agree that it is a problem and request.POST also has to parse application/json?
I am asking this because I thought there must be a DRF design reason behind request.POST is not parsing application/json.
If you conceive this to be a bug rather than a DRF design, I can raise a fix PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants