When you tries to do http post with a JSON data / payload to your Django REST Framework ( DRF ) based server, sometimes you may get the “Bad Request” error with http code 400 as below,
Bad Request: /YOUR_API/
[DD/Month/YEAR 19:31:51] "POST /users/ HTTP/1.1" 400 75
When we checked what is the meaning of this error from Django documentation, it is defined as,
“The 400 (bad request) – defaults.bad_request(request, exception, template_name=’400.html’)
When a SuspiciousOperation is raised in Django, it may be handled by a component of Django (for example resetting the session data). If not specifically handled, Django will consider the current request a ‘bad request’ instead of a server error.
django.views.defaults.bad_request, is otherwise very similar to the server_error view, but returns with the status code 400 indicating that the error condition was the result of a client operation. By default, nothing related to the exception that triggered the view is passed to the template context, as the exception message might contain sensitive information like filesystem paths.
bad_request views are also only used when DEBUG is False.”
When we checked, what this “SuspiciousOperation” is .. as per documentation it is defined as,
SuspiciousOperation – exception SuspiciousOperation[source][/source]
The SuspiciousOperation exception is raised when a user has performed an operation that should be considered suspicious from a security perspective, such as tampering with a session cookie.Subclasses of SuspiciousOperation include: DisallowedHost , DisallowedModelAdminLookup, DisallowedModelAdminToField, DisallowedRedirect, InvalidSessionKey, RequestDataTooBig, SuspiciousFileOperation, SuspiciousMultipartForm, SuspiciousSession, TooManyFieldsSent
If a SuspiciousOperation exception reaches the WSGI handler level it is logged at the Error level and results in a HttpResponseBadRequest.
Now, coming back to our issues where we seen this “Bad Request” as mentioned earlier, lets try to do http POST to our server,
$ curl -v -k -H "Accept: application/json" -H Content-Type:application/json -X POST -d '{"username":lynxbee,"email":social(at)lynxbee.com,"age":"23"}' http://192.168.0.105:8000/users/
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 192.168.0.105...
* TCP_NODELAY set
* Connected to 192.168.0.105 (192.168.0.105) port 8000 (#0)
> POST /users/ HTTP/1.1
> Host: 192.168.0.105:8000
> User-Agent: curl/7.58.0
> Accept: application/json
> Content-Type:application/json
> Content-Length: 57
>
* upload completely sent off: 57 out of 57 bytes
< HTTP/1.1 400 Bad Request
< Date: Sat, 15 Aug 2020 16:45:24 GMT
< Server: WSGIServer/0.2 CPython/3.6.9
< Content-Type: application/json
< Vary: Accept, Cookie
< Allow: GET, POST, HEAD, OPTIONS
< X-Frame-Options: DENY
< Content-Length: 75
< X-Content-Type-Options: nosniff
< Referrer-Policy: same-origin
<
* Connection #0 to host 192.168.0.105 left intact
Notice above that when we sent http POST with the JSON , we got in reply “< HTTP/1.1 400 Bad Request” .. now if we closely look at the JSON and the error we received, we can see that we are missing double quote in JSON ‘{“username”:lynxbee,”email”:sociallynxbee.com,”age”:”23″}’ .. for username and email..
hence now lets correct the JSON by adding double quote for “lynxbee” and “social(at)lynxbee.com” ‘{“username”:”lynxbee”,”email”:”social(at)lynxbee.com”,”age”:”23″}’ and do http POST again,
$ curl -v -k -H "Accept: application/json" -H Content-Type:application/json -X POST -d '{"username":"lynxbee","email":"social(at)lynxbee.com","age":"23"}' http://192.168.0.105:8000/users/
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 192.168.0.105...
* TCP_NODELAY set
* Connected to 192.168.0.105 (192.168.0.105) port 8000 (#0)
> POST /users/ HTTP/1.1
> Host: 192.168.0.105:8000
> User-Agent: curl/7.58.0
> Accept: application/json
> Content-Type:application/json
> Content-Length: 61
>
* upload completely sent off: 61 out of 61 bytes
< HTTP/1.1 201 Created
< Date: Sat, 15 Aug 2020 16:45:48 GMT
< Server: WSGIServer/0.2 CPython/3.6.9
< Content-Type: application/json
< Vary: Accept, Cookie
< Allow: GET, POST, HEAD, OPTIONS
< X-Frame-Options: DENY
< Content-Length: 61
< X-Content-Type-Options: nosniff
< Referrer-Policy: same-origin
<
* Connection #0 to host 192.168.0.105 left intact
{"username":"lynxbee","email":"social(at)lynxbee.com","age":"23"}
And we can see the error has gone..
So final solution for this error
Most probably “Bad Request” error is sent when something is wrong from the data received from client to Django Server, hence observe clearly for any mistakes in data sent or http requests sent to server and correct. For example, as we were trying to send invalid json to server hence we got “Bad Request”