puppeteer: [Bug]: ProtocolError: Could not load body for this request. This might happen if the request is a preflight request

Bug expectation

Background: I do an ui test Version: puppeteer: 19.7.5 scene: I test a form, so i fill a form to create a item, then it will change the url automatically with detail. Now, i need to the request’s response for creating. But it catch a error ProtocolError: Could not load body for this request. This might happen if the request is a preflight request. There is no Cross-domain request. code: The test case is following. ` javascript

it('create new Page', async () => {
  await expect(page).toClick('button>span', {
    text: 'create new Page',
});

const { confirm, modal } = await waitForModal(page);
await expect(modal).toFill(
  ".input-module-content>input[placeholder='please input ']",
  // fill a name
  WIKI_SPACE_NAME
)
// then click confirm
const [response] = await Promise.all([
  page.waitForResponse(WikiInterceptors.wikiSpaceAdd({ teamUUID })),
  confirm()
]);

// wait navigation
await page.waitForNavigation();

// parse the reponse but catch a error 
const spaceInfo = await response.json();

await expect(spaceInfo).toBeDefined();

spaceUUID = spaceInfo?.uuid;})`

what i try to solve.

  1. launch with params launch: { args: [ "--no-sandbox", "--disable-gpu", "--disable-setuid-sandbox", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-renderer-backgrounding" ], }
  2. change the request Interception mode const [response] = await Promise.all([ page.waitForResponse((response) => response.url().include('xxx'), { waitUntil: "networkidle0", }), confirm() ]); There are all don’t work out! Help~~~

Bug behavior

  • Flaky
  • PDF

Minimal, reproducible example

it("create new Page", async () => {
    await expect(page).toClick("button>span", {
      text: "create new Page",
    });

    const { confirm, modal } = await waitForModal(page);

    await expect(modal).toFill(
      ".input-module-content>input[placeholder='please input ']",
      // fill a name
      WIKI_SPACE_NAME
    );

    // then click confirm
    const [response] = await Promise.all([
      page.waitForResponse(WikiInterceptors.wikiSpaceAdd({ teamUUID })),
      confirm()
    ]);

    // wait navigation
    await page.waitForNavigation();

    // parse the reponse but catch a error 
    const spaceInfo = await response.json()

    await expect(spaceInfo).toBeDefined();

    spaceUUID = spaceInfo?.uuid;
  });

Error string

ProtocolError: Could not load body for this request. This might happen if the request is a preflight request

Puppeteer configuration

No response

Puppeteer version

19.7.5

Node version

v16.14.2

Package manager

pnpm

Package manager version

8.5.0

Operating system

macOS

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 10
  • Comments: 25

Most upvoted comments

Workaround

Add this condition in the waitForResponse predicate:

const response = await page.waitForResponse(response =>
  response.request().method().toUpperCase() != "OPTION"
  && ...
);

Workaround

Add this condition in the waitForResponse predicate:

const response = await page.waitForResponse(response =>
  response.request().method().toUpperCase() != "OPTION"
  && ...
);

Nice, just change it to “OPTIONS”.

same problem

Still existing

Same problem

Same, too!

This is not a puppeteer problem, this is a chrome problem. When there is a thread interrupt in the body of a page, the protocol will not return a body. Examples: <body><script>window.location = 'http://...'</script></body> or <body><form id="myform">....</form> <script>getElementById('myform').submit()</script></body>

In firefox everything works as it should.

In my case, I solved it this way:

  1. Catch the response you want page.on("response", async (response) => {...
  2. Save the original request made for that response:
const originalRequest = await response.request();

responseData = {
    url: originalRequest.url(),
    method: originalRequest.method(),
    headers: originalRequest.headers(),
    body: originalRequest.postData(),
}

return responseData
  1. Bring it to the client-side and make the request again with the same parameters
fetch(`${YOURSERVER}`)
    .then(async (result) => {

        const data: {
            url: any;
            method: any;
            headers: any;
            body: any;
        } = await result.json();

        await fetch(data.url, {
            method: data.method,
            headers: data.headers,
            body: data.body,
            mode: "no-cors",
        }).then((result) => {
            //the data you wanted
        });
    })

In my specific case, the data.url already contained what I need, so simply setting this and clicking on it started the download of the required file.

<a href={data.url}>Download Link</a>

Hope that helps someone.

I solved it in my case too, but it was a different circumstance. In my situation I was intercepting the response I was interested in, but the page was redirecting shortly after. Although I had the right response (POST method), getting the body for it was throwing the error.

The way I solved it was to make a GET request to the URL by using page.goto, intercept and modify the request method to POST

// first, setup request interception and modification
page.on('request', (req) => {
  if (req.url() === 'https://example.com/abc' && req.method() === 'GET') {
    // modify the request we're interested in
    return req.continue({
        method: "POST",
        postData: "x=y",
        headers: {
            ...req.headers(),
            "Content-Type": "application/x-www-form-urlencoded"
    });
  } else {
    // continue as normal with other requests
    req.continue()
  }
})

// make GET request which gets modified to POST by interception
const response = await page.goto('https://example.com/abc')
// now the body is available, no redirect anymore
const body = await response.text()