0

Good Day All, I'm trying to do a POST request using the puppeteer headless chrome library. I can't seem to get the below code to work.

    // Get csrf token
    let token = await page.evaluate(() => document.querySelector('[name="CSRFToken"]').value);

    let postResponse = await page.evaluate(async(token, cookies) => {    

    let response = fetch("/loyalty/points", {
          method : 'POST',
          cookie : cookies,
          postData : 'CSRFToken=' + token,      
        }).then(response => response.text()).catch(error => console.log(error));

        return response;

      });

      console.log('Final response');
      console.log(postResponse);

I keep on getting an error that the CSRF token has not been set or that the cookie is invalid.

My question is, am I using the correct method in puppeteer to do a POST? If so, is there any way for me to do some debugging that I can see the actual POST request that was sent?

I appreciate any advice or help. Thanks

Chesneycar
  • 504
  • 13
  • 39

1 Answers1

1

You are not creating a request body: hence the error. The postData attribute you set on the request object is not any known attribute, so it won't be set on the request either, meaning that the server will never see your CSRF token. You should look into the MDN docs on fetch().

I believe you should be all good by simply replacing postData with body, but it's hard to know without access to your endpoint. For all we know it might require special headers.

Given that you only post normal form data (which is implied by your key=value code), I would also start using the FormData objects provided by your browser to avoid manual coding of implementation details.

const formData = new FormData();

formData.append("CSRFToken", token);

const response = fetch("/loyalty/points", {
      method : 'POST',
      cookie : cookies,
      body   : formData,
      headers : {
        'cookie' : cookies,
        /* other headers you need, possibly content-type (see below) */
      },   
    }).then(response => response.text()).catch(error => console.log(error));

    return response;
  });

Caveat: using the FormData API will always set the content-type of the data to multipart/form-data. If your server for some reason doesn't support that encoding, and you need to use application/x-www-form-urlencoded (see here for difference), you can't blindly change the Content-Type: you also need to url encode the content.

For debugging I would simply use a normal Chrome instance to see this. You should be able to run the code there and see the network requests in DevTools (where it would be immediately noticeable that you POST an empty request).

oligofren
  • 15,352
  • 12
  • 75
  • 134
  • Hi, thanks for your help. I ended up refactoring my code but still using the string in the body. In the end it worked perfectly. The problem was the the token paramter was never received by my function. I had to do something like this ` let postResponse = await page.evaluate(fetchLoyaltyPoints, token, cookies);` and my fetchLoyaltyPoints function just had to take those 2 parameters as well eg. ` function fetchLoyaltyFunction(token, cookies){...` – Chesneycar Jun 06 '18 at 06:51