当部署到heroku而不是本地时,fetch调用出现503错误

e4yzc0pl  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(112)

**问题:**当我在部署到heroku后向服务器发送特定的get请求时,每次都会收到503错误,并且应用程序在点击提交时不会完成预期的操作。该请求专门用于触发puppeteer屏幕截图代码并返回一个包含屏幕截图的zip文件到客户端。这在本地工作正常,只有在部署后才会失败。
**值得注意的错误:**我的heroku日志在截图的一半时产生了一个请求超时错误,代码是H12。我现在还不清楚这是什么原因,因此应该采取什么解决方案(甚至是如何最好地找到答案)。
**应用程序:**我构建了一个内部团队应用程序,它接收一个URL,对该URL上的所有横幅进行屏幕截图,然后将它们打包到一个zip文件中,并将该文件返回给客户端下载。
前端代码:

fetch(`/dcsgrab?tearsheetUrl=${screenShotData}`)
      .then((response) => response.json())
      .then((data) => {
        zipBlob = new Blob([new Uint8Array(data.zipFile.data)], {type: "octet/stream"});
        url = window.URL.createObjectURL(zipBlob);
        zipDownload = document.createElement("a");

        setMessageData(data.message);
        setZipData(zipBlob);

        zipDownload.href = url;
        zipDownload.download = "screenshot-download.zip";
        document.body.appendChild(zipDownload);
        zipDownload.click();
      });
  };

后端编码:

app.get('/dcsgrab', (request, response) => {
    const zip = new AdmZip();

    (async () => {
        const browser = await puppeteer.launch({
            headless: true,
            executablePath: executablePath(),
            args: [
              '--no-sandbox',
              '--disable-setuid-sandbox',
              '--single-process',
            ],
        });

        let screenshotCounter = 1;

        const page = await browser.newPage();

        page.setViewport({width: 1280, height: 6000, deviceScaleFactor: PIXEL_DENSITY});

        await page.goto(request.query.tearsheetUrl, { waitUntil: 'networkidle0' });

        /**
       * Checks if the pagination button is active
       * @return {Promise.<Boolean>} Promise which resolves with a true boolean if the button is active
       */
      async function isNextButtonActive() {
        return await page.evaluate((selector) => {
          return !document.querySelector(selector).disabled;
        }, NEXT_SELECTOR);
      }

      /**
       * Clicks the pagination button
       * @return {Promise} Promise which resolves when the element matching selector is successfully clicked. The Promise will be rejected if there is no element matching selector
       */
      async function clickNextButton() {
        return await page.click(NEXT_SELECTOR, {delay: 100});
      }

      /**
       * Waits for the loading spinner widget to go away, indicating the iframes have been added to the page
       * @return {Promise.undefined}
       */
      async function waitForLoadingWidget() {
        return await page.waitForSelector('.preview-loading-widget', {hidden: true}).then(() => {
          console.log('Loading widget is gone');
        })
          .catch(e => {
            console.log(e.message);
          });
      }

      /**
       * Screenshot the creative elements on the current page
       * @return {Promise.<Array>} Promise which resolves with an array of clipping paths
       */
        async function getScreenShots() {
            const rects = await page.$$eval(PREVIEW_SELECTOR, iframes => {
              return Array.from(iframes, (el) => {
                const {x, y, width, height} = el.getBoundingClientRect();

                return {
                  left: x,
                  top: y,
                  width,
                  height,
                  id: el.id,
                };
              });
            }, PREVIEW_SELECTOR).catch(e => {
              console.error(e.message);
            });

            return Promise.all(rects.map(async (rect) => {
              return await page.screenshot({
                clip: {
                  x: rect.left,
                  y: rect.top,
                  width: rect.width,
                  height: rect.height,
                },
              }).then((content) => {
                zip.addFile(`screenshot-${screenshotCounter++}.png`, Buffer.from(content, "utf8"), `screenshot ${screenshotCounter++} saved`);
                console.log(`${rect.id} element captured and stored in zip`);
              })
                .catch((e) => {
                  console.error(e.message);
                });
            }));
        }

        // Wait a bit then take screenshots
      await new Promise(resolve => setTimeout(resolve, DELAY_FOR_ANIMATION));
      await getScreenShots().catch((e) => console.error(e.message));

        // Continue taking screenshots till there are no pages left
      while (await isNextButtonActive()) {
        await clickNextButton();
        await waitForLoadingWidget();
        await new Promise(resolve => setTimeout(resolve, DELAY_FOR_ANIMATION)),
        await getScreenShots().catch((e) => console.error(e.message));
      }

        await browser.close();

        const zipToSend = zip.toBuffer();

        response.json({ 
            message: 'Screenshots are done!\nPlease check the zip file that was just downloaded.',
            zipFile: zipToSend
        });
    })();
});

Heroku日志:

2023-03-23T19:27:43.174105+00:00 heroku[web.1]: Restarting
2023-03-23T19:27:43.189825+00:00 heroku[web.1]: State changed from up to starting
2023-03-23T19:27:44.190045+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2023-03-23T19:27:44.368177+00:00 heroku[web.1]: Process exited with status 143
2023-03-23T19:27:53.000000+00:00 app[api]: Build succeeded
2023-03-23T19:28:07.523862+00:00 heroku[web.1]: Starting process with command `npm start`
2023-03-23T19:28:09.144631+00:00 app[web.1]: 
2023-03-23T19:28:09.144660+00:00 app[web.1]: > preview-sheet-grabber-react@1.0.0 start
2023-03-23T19:28:09.144661+00:00 app[web.1]: > node server/server.js
2023-03-23T19:28:09.144661+00:00 app[web.1]: 
2023-03-23T19:28:09.428387+00:00 app[web.1]: Server is listening on port 21309
2023-03-23T19:28:09.838525+00:00 heroku[web.1]: State changed from starting to up
2023-03-23T19:28:10.596907+00:00 heroku[router]: at=info method=GET path="/" host=dcsgrab.herokuapp.com request_id=f0b15bcd-7eb4-4028-b5a9-2a6f76496c05 fwd="24.16.69.155" dyno=web.1 connect=0ms service=86ms status=200 bytes=944 protocol=https
2023-03-23T19:28:10.699774+00:00 heroku[router]: at=info method=GET path="/static/js/main.1910c761.js" host=dcsgrab.herokuapp.com request_id=e775658f-f56d-4db8-bcb2-71de15b0d87d fwd="24.16.69.155" dyno=web.1 connect=0ms service=4ms status=200 bytes=218121 protocol=https
2023-03-23T19:28:11.706348+00:00 heroku[router]: at=info method=GET path="/static/css/main.69947f1d.css" host=dcsgrab.herokuapp.com request_id=5340c5b9-b516-4a5a-99f5-851b421b1949 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=3167 protocol=https
2023-03-23T19:28:11.818395+00:00 heroku[router]: at=info method=GET path="/static/css/main.69947f1d.css.map" host=dcsgrab.herokuapp.com request_id=ffcf15de-1af4-4dee-83d1-99c0c811c73f fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=5370 protocol=https
2023-03-23T19:28:11.820299+00:00 heroku[router]: at=info method=GET path="/static/js/main.1910c761.js.map" host=dcsgrab.herokuapp.com request_id=e7c588ad-c085-4a12-bd1b-d3c4433d48de fwd="24.16.69.155" dyno=web.1 connect=0ms service=5ms status=200 bytes=746644 protocol=https
2023-03-23T19:28:11.907618+00:00 heroku[router]: at=info method=GET path="/static/media/essence_mediacom_logo-nobg-color_corrected.764800408369a0f7cf88.png" host=dcsgrab.herokuapp.com request_id=f1f5ed8c-eda8-46a1-af0f-8e87e8d2d615 fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=16759 protocol=https
2023-03-23T19:28:11.993490+00:00 heroku[router]: at=info method=GET path="/static/media/essencemediacom_icon.a48332799f21c2163415.png" host=dcsgrab.herokuapp.com request_id=05b087a5-cccc-4efb-9da4-d4b9ae3af678 fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=14971 protocol=https
2023-03-23T19:28:12.189730+00:00 heroku[router]: at=info method=GET path="/essencemediacom_icon.png" host=dcsgrab.herokuapp.com request_id=5921b175-24b7-43ef-8db8-1a3df51588ad fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=14971 protocol=https
2023-03-23T19:28:12.473057+00:00 heroku[router]: at=info method=GET path="/manifest.json" host=dcsgrab.herokuapp.com request_id=bfa7629b-b6ad-49c1-a4a0-bffb968bfbb6 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=787 protocol=https
2023-03-23T19:28:12.555689+00:00 heroku[router]: at=info method=GET path="/logo192.png" host=dcsgrab.herokuapp.com request_id=174be88c-84fd-4046-8862-35c77bcef675 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=5622 protocol=https
2023-03-23T19:28:38.626764+00:00 app[web.1]: safe-frame-1 element captured and stored in zip
2023-03-23T19:28:39.116534+00:00 app[web.1]: safe-frame-5 element captured and stored in zip
2023-03-23T19:28:39.497607+00:00 app[web.1]: safe-frame-2 element captured and stored in zip
2023-03-23T19:28:39.954761+00:00 app[web.1]: safe-frame-4 element captured and stored in zip
2023-03-23T19:28:40.270808+00:00 app[web.1]: safe-frame-3 element captured and stored in zip
2023-03-23T19:28:41.373398+00:00 app[web.1]: Loading widget is gone
2023-03-23T19:28:47.380186+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/dcsgrab?tearsheetUrl=https://www.google.com/doubleclick/preview/dynamic/previewsheet/CMP6kgUQ3cxBGLbTkhUg97ss" host=dcsgrab.herokuapp.com request_id=8d21b818-58e6-4f76-bd08-2d00050801b4 fwd="24.16.69.155" dyno=web.1 connect=0ms service=30000ms status=503 bytes=0 protocol=https
2023-03-23T19:28:56.769792+00:00 app[web.1]: safe-frame-8 element captured and stored in zip
2023-03-23T19:28:57.162674+00:00 app[web.1]: safe-frame-7 element captured and stored in zip
2023-03-23T19:28:57.598963+00:00 app[web.1]: safe-frame-6 element captured and stored in zip
2023-03-23T19:28:57.985009+00:00 app[web.1]: safe-frame-9 element captured and stored in zip
2023-03-23T19:28:58.436801+00:00 app[web.1]: safe-frame-10 element captured and stored in zip
2023-03-23T19:28:58.884653+00:00 app[web.1]: Loading widget is gone
jslywgbw

jslywgbw1#

看看Heroku的官方错误代码H12,它说:
HTTP请求的完成时间超过30秒
因此,您的服务器可能无法在30秒内生成对端点/dcsgrab的响应,因此Heroku生成了错误。

相关问题