[Django backend] wechat applet post requests to return 403 or 500 solutions

Posted by rel on Sun, 27 Feb 2022 10:08:32 +0100

Django is simply used to provide the back-end interface for wechat applet. I am responsible for the back-end interface and my classmates are responsible for the front-end. We tested that there is no problem with the get request, but when sending the post request, the return values received by the front-end are always 500 and 403.
(PS: if you want to see the solution directly, you can click "solution" below to jump to it)

1. Return 500 (server error)

Front end code

Back end interface

def get2(request):
    if request.method == "POST":
        id = request.POST.get('id')
        return HttpResponse({"result": id+5})

As can be seen from the front-end code above, there is no addition / at the end of the url, and the return value is 500. Then I delete the if statement in the back-end interface and return it directly, but the return value of the front-end remains unchanged, which is 500.

Try a way

Modify front-end header

I found some information on the Internet, saying that the header of the front-end code was modified:

header = {
	'content-type': 'application/x-www-form-urlencoded',
}

After modification, it is still wrong, and the return value is still 500.

Modify how the backend gets parameters

After reading a lot of materials, I feel that there is no problem with the writing of the front-end code, so I think there is an error when the back-end obtains the parameters of the post request, so I try to obtain the parameters in other ways:

  • First kind
def get2(request):
	req_data = self.request.body
	req_data = json.loads(req_data)
	id = req_data.get('id')
	return HttpResponse({"result": id+5})
  • Second
def get2(request):
	id = request.data['id']
	return HttpResponse({"result": id+5})

Neither of the above methods can work. The return value is still 500. At this time, I feel very strange. I just want to see what happened after these requests were sent. So I added a print statement to the back-end code to judge the type of request:

def get2(request):
	print(request.method)
	id = = request.data['id']
	return HttpResponse({"result": id+5})

The output result surprised me, because it outputs "GET", so it is easy to understand that the return value of the request is 500. Because I always use the format of obtaining POST request parameters, the service has an error and returns 500. Then I went to query the record of the request. I found that the return value of each POST request is 301 (that is, permanent redirection: this page is permanently transferred to another URL). So I went to search for the reasons and solved the following problems.

2. Return 403 (access is prohibited, and the server receives the request but refuses to provide service)

Through the previous analysis, I feel that things are very strange, because each POST request is permanently redirected. After querying some data, I learned that when django orients the url, if the end is not '/', it will be redirected to the url with '/', i.e. 301, and then the empty request will be redirected and become get.
So I excitedly asked the front-end students to add /, but after a test, the return value became 403.

Try a way

Modify nginx related configuration

Because nginx+uwsgi is used in the deployment of django project, I saw someone on the Internet saying that nginx may cause the post request to return 403. After searching some materials, I felt that the solutions were troublesome, so I didn't adopt them. (you can search by yourself)

resolvent

When searching the POST request always returns 403, I came across a data, which mentioned that this is a cross domain request problem

(the CSRF template tag required by the form in django can prevent cross site request forgery. CSRF enables malicious sites visited by the client browser to make requests to your own server. Therefore, the csrf_token provided by django makes it easy for your django server and site to be protected from such malicious attacks. If your form is not protected by csrf_token, django will return 40 3 disable page. This is a form of protection for your website, especially if the token is not intentionally omitted.)

But in some cases, Django sites don't want to use csrf_token protects its form, so Django provides a decorator * * @csrf_exempt * *, this decorator marks the view as unprotected by the middleware.
Therefore, the following modifications are made:

#Import CSRF into the program_ exempt
from django.views.decorators.csrf import csrf_exempt
#Add @ CSRF before the function that wants to accept the POST request_ exempt
@csrf_exempt
def get2(request):
	print(request.method)
	id = request.data['id']
	return HttpResponse({"result": id+5})

In this way, the front-end request can normally get the return value, and the return status is 200.

summary

  • The url of the front end needs to end with /
  • Modify the front-end 'content type'
header = {
	'content-type': 'application/x-www-form-urlencoded',
}
  • Front end interface function with @ csrf_exempt
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def get2(request):
	print(request.method)
	id = request.data['id']
	return HttpResponse({"result": id+5})

If there is anything wrong, please correct it. Thank you.

Topics: Python Django Back-end Mini Program post