1
votes

I am trying to generate a csrf token in javascript and use that with a POST request using fetch. In my html, I have the following script tag under head to generate the csrf token:

<head>
    <script type="text/javascript">
        var user = '{{request.user}}'

        function getCookie(name) {
            let cookieValue = null;
            if (document.cookie && document.cookie !== '') {
                const cookies = document.cookie.split(';');
                for (let i = 0; i < cookies.length; i++) {
                    const cookie = cookies[i].trim();
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
        var csrftoken = getCookie('csrftoken');

        console.log(csrftoken)
    </script>
</head>

Then under body, I have the following script tag where I retrieve the csrftoken variable and pass it to the 'X-CSRFToken' header in fetch():

<body>
    <script type="text/javascript">
        console.log('Hello World')
        console.log(csrftoken)

        var updateButtons = document.getElementsByClassName('update-cart')

        for(i = 0; i < updateButtons.length; i++){
            updateButtons[i].addEventListener('click', function(){
                var productId = this.dataset.product
                var action = this.dataset.action
                console.log('productId: ', productId, 'action: ', action)

                console.log('user: ', user)

                if(user === 'AnonymousUser'){
                    console.log('Not logged in.')
                }else{
                    updateUserOrder(productId, action)
                }
            })
        }

        function updateUserOrder(productId, action){
            console.log('User is authenticated. Sending data...')
            console.log(csrftoken)

            var url = '/update_item/'

            fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type':'application/json',
                    'X-CSRFToken':csrftoken,
                },
                body: JSON.stringify({'productId': productId, 'action': action})
            })

            .then((response) => {
                return response.json()
            })

            .then((data) => {
                console.log('data: ', data)
            })
        }
    </script>
</body>

The csrftoken variable is displayed by all the console.log() calls but I still get the following exceptions:

(index):169 POST http://127.0.0.1:8000/update_item/ 500 (Internal Server Error)
updateUserOrder
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

views.py,

def update_item(request):
    data = json.loads(request.data)
    product_id = data['productId']
    action = data['action']

    print('action: ', action)
    print('product_id: ', product_id)

    customer = request.user.customer
    product = Product.objects.get(id=product_id)

    order, created = Order.objects.get_or_create(customer=customer, complete=False)
    orderitem, created = OrderItem.objects.get_or_create(order=order, product=product)

    if action == 'add':
        orderitem.quantity += 1
    elif action == 'remove':
        orderitem.quantity -= 1

    orderitem.save()

    if orderitem.quantity <= 0:
        orderitem.delete()

    return JsonResponse('Item was added.', safe=False)

I cannot seem to figure out whether it is a syntax error or if I am setting the 'X-CSRFToken' header wrong. Other similar answers did not help.

1
You've to check how did your server handled the request, and ended up to an error. < most likely is in the JSON, because the server has responsed with an error page. - Teemu
@Teemu On server, I am returning Json response. I have updated my question with my view function so you can check. But the POST request causes a failed csrf verification, so I am getting that error. - Kamruzzaman Tauhid
No, you're intenting to return JSON, but the server-side code fails (500 Internal server error), and it responses either with an error page or an error message containing that <. Hit F12, open the Networktab and do something on the page so that the request is called. When the server responses, the response can be seen in the list in Network tab. Click the response, and check what actually is there in the response body. Then go to the server logs to see what went wrong. - Teemu
Correct. The error was in my server side code. In views.py, I typed data = json.loads(request.data). But it should be data = json.loads(request.body). - Kamruzzaman Tauhid

1 Answers

0
votes

Solved. It was not an issue with my javascript or the csrftoken variable therein. Rather it was in my server code. In views.py, I typed data = json.loads(request.data). But it should be data = json.loads(request.body).