djangohttp-postfetch-apihttp-methodhttp-put

Django with Javascript fetch API: POST works but all other unsafe methods are forbidden


I am working on this CS50W project.

When using the fetch API to send POST requests to the server, everything worked fine. After I changed the method to PUT, or any other unsafe methods, things stopped working.

Javascript

let like_form = document.querySelector('#like-form');
let data = new FormData(like_form);

fetch(`post/${post_id}/like`, {
  method: 'POST',
  body: data,
  credentials: "same-origin"
})

views.py

@login_required
def like_post(request, post_id):

    if request.method == 'POST':
        post = get_post(post_id)
        if post:
            if request.user in post.liked_by.all():
                post.liked_by.remove(request.user)
                status = False
            else:
                post.liked_by.add(request.user)
                status = True
            
            return JsonResponse({
                'message': 'Success.',
                'status': status
            }, status=200)

index.html

<form id='like-form'>
    {% csrf_token %}
</form>

Output using POST

{message: 'Success.', status: false}

Output using PUT

PUT http://127.0.0.1:8000/post/17/like 403 (Forbidden)
Forbidden (CSRF token missing.): /post/17/like

The only thing I changed was the method in fetch and views.py

Any help will be appreciated.


Solution

  • After going into the source code, I found out that for PUT, the csrf_token is read from the headers of the request instead of the body. Therefore adding

    headers: {
      'x-csrftoken': CSRF_TOKEN_ELEMENT.value
    }
    

    solved the problem