prismicio/prismic-next

Unicode characters not encoded in preview redirection URL

Opened this issue · 2 comments

Versions

  • @prismicio/next: 0.1.9
  • next: 12.3.4
  • node: 16.18.1

Reproduction

  1. Setup a document type page, with an uid field and the following route resolver:
  {
    type: 'page',
    path: '/:uid',
  }
  1. Preview a page document with an uid containing unicode characters, like тест.

What is expected?

The тест page document is previewed.

What is actually happening?

An error page is displayed, and Next.js logs the following error:

TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["Location"]
    at ServerResponse.setHeader (node:_http_outgoing:647:3)
    at ServerResponse._res.setHeader ([REDACTED]/node_modules/next/dist/server/base-server.js:127:24)
    at setHeadersFromObject ([REDACTED]/node_modules/next/dist/compiled/compression/index.js:46:680)
    at ServerResponse.setWriteHeadHeaders ([REDACTED]/node_modules/next/dist/compiled/compression/index.js:46:914)
    at ServerResponse.writeHead ([REDACTED]/node_modules/next/dist/compiled/compression/index.js:46:121)
    at Object.redirect ([REDACTED]/node_modules/next/dist/server/api-utils/index.js:35:9)
    at ServerResponse.apiRes.redirect ([REDACTED]/node_modules/next/dist/server/api-utils/node.js:351:59)
    at redirectToPreviewURL (webpack-internal:///(api)/../node_modules/@prismicio/next/dist/redirectToPreviewURL.js:18:16)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async preview (webpack-internal:///(api)/./src/pages/api/preview.ts:30:9) {
  code: 'ERR_INVALID_CHAR',
  page: '/api/preview'
}

After some research the error is located within redirectToPreviewURL, with the underlying res.redirect call. This function tries to send a response with the Location header set with the redirection URL, but it seems that Node doesn't allow raw unicode characters in HTTP headers.

Forcing each path segment in the to be URL encoded solves the issue, this is my workaround:

    const originalRedirect = res.redirect;
    await redirectToPreviewURL({
      req,
      res: {
        ...res,
        redirect: ((url: string) => {
          const encodedUrl = url.split('/').map(encodeURIComponent).join('/');
          return originalRedirect(encodedUrl);
        }) as NextApiResponse['redirect'],
      },
      client,
      basePath,
    });

This issue has been labeled as a bug since it was created using the 🚨 Bug Report Template.

Hi there, thank you so much for the report!

Following our Maintenance Process, we will review your bug report and get back to you next Wednesday. To ensure a smooth review of your issue and avoid unnecessary delays, please make sure your issue includes the following:

  • Information about your environment and packages you use (Node.js version, package names and their versions, etc.)
    Feel free to attach a copy of your package.json file.
  • Any troubleshooting steps you already went through
  • A minimal reproduction of the issue, and/or instructions on how to reproduce it

If you have identified the cause of the bug described in your report and know how to fix it, you're more than welcome to open a pull request address it. Check out our quick start guide for a simple contribution process.

If you think your issue is a question (not a bug) and would like quicker support, please close this issue and forward it to an appropriate section on our community forum: https://community.prismic.io

- The Prismic Open-Source Team

Hey @sylvaingi, thanks for the bug report. I haven't had a chance to look at this yet, but I just wanted to let you know it isn't being ignored. 🙂