Skip to content

support non-ASCII filesystem bundle paths with metro server#1538

Closed
bradleyayers wants to merge 1 commit intofacebook:mainfrom
bradleyayers:patch-1
Closed

support non-ASCII filesystem bundle paths with metro server#1538
bradleyayers wants to merge 1 commit intofacebook:mainfrom
bradleyayers:patch-1

Conversation

@bradleyayers
Copy link
Copy Markdown
Contributor

@bradleyayers bradleyayers commented Jul 23, 2025

Note

This PR was modified by @vzaidman and merged in 92ac74c with a more upstream decoding of URLs to prevent non-ASCII from crashing Metro.

However, while Metro would now indeed not crash, Metro doesn't fully support non-ASCII files as of this PR.

Instead, the later merged commit cb02cdb adds a comprehensive support to non-ASCII in Metro with tests.

The split into two PRs is intended to credit the author of this PR and to allow us to revert the latter more complex code without removing this fix.

Also see subsequent commits: 71e158a and 98badca

In a codebase with non-ascii characters in file paths (e.g. Japanese or Chinese characters), metro has an error when serving bundles:

TypeError: Invalid character in header content

This was reported in the Expo project expo/expo#27397 but it's not Expo code and was later closed.

The problem is fairly simple—HTTP headers need to use ASCII characters only, but filesystems are not limited to ASCII so trying to put a filesystem path directly into a HTTP header value is going to cause a problem.

The solution also seems relatively simple—URL encode the path so that it uses percent encoding of non-ASCII characters.

I did three tests of this code, looking at the response headers for the chunk served by metro to look for backwards compatibility of using new URL(…) on paths that don't use non-ASCII characters.

with new URL(…) patch and /你/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/%E4%BD%A0/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false

---

with new URL(…) and /ni/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/ni/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false

---

original code with /ni/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/ni/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false

This demonstrates that it's backwards compatible, while properly encoding non-ASCII characters.

Summary

Changelog: [Fix] non-ascii files processed by Metro no longer crash the server

In a codebase with non-ascii characters in file paths (e.g. Japanese or Chinese characters), metro has an error when serving bundles:

```
TypeError: Invalid character in header content
```

This was reported in the Expo project expo/expo#27397 but it's not Expo code and was later closed.

The problem is fairly simple—HTTP headers need to use ASCII characters only, but filesystems are not limited to ASCII so trying to put a filesystem path directly into a HTTP header value is going to cause a problem.

The solution also seems relatively simple—URL encode the path so that it uses percent encoding of non-ASCII characters.

I did three tests of this code, looking at the response headers for the chunk served by metro to look for backwards compatibility of using `new URL(…)` on paths that don't use non-ASCII characters.

```
with new URL(…) patch and /你/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/%E4%BD%A0/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false

---

with new URL(…) and /ni/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/ni/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false

---

original code with /ni/ path segment

Content-Location: http://localhost:8081/projects/app/src/client/wiki/ni/hello.bundle//&platform=web&dev=true&hot=false&lazy=true&transform.routerRoot=src%2Fapp&transform.reactCompiler=true&modulesOnly=true&runModule=false
```

This demonstrates that it's backwards compatible, while properly encoding non-ASCII characters.
@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Jul 23, 2025
@facebook-github-bot
Copy link
Copy Markdown
Contributor

@vzaidman has imported this pull request. If you are a Meta employee, you can view this in D78799358.

vzaidman pushed a commit to vzaidman/metro that referenced this pull request Aug 7, 2025
…#1538)

Summary:
In a codebase with non-ascii characters in file paths (e.g. Japanese or Chinese characters), metro has an error when serving bundles:

```
TypeError: Invalid character in header content
```

This was reported in the Expo project expo/expo#27397 but it's not Expo code and was later closed.

The problem is fairly simple—HTTP headers need to use ASCII characters only, but filesystems are not limited to ASCII so trying to put a filesystem path directly into a HTTP header value is going to cause a problem.

The solution also seems relatively simple—URL encode the path so that it uses percent encoding of non-ASCII characters.

As suggested in https://velog.io/demian/RN-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0-TypeError-Invalid-character-in-header-content-X-React-Native-Project-Root, some people were  adding the following middleware to fix that issue:
```
function createMetroStatusMiddleware(metroConfig) {
    return (_req, res)=>{
        res.setHeader("X-React-Native-Project-Root", new URL(metroConfig.projectRoot));
        res.end("packager-status:running");
    };
}
```
Instead, I went to the root cause, and improved the parsing of the URL for both `sourceUrl` and `sourceMapUrl` fixing both the issue with serving bundles and the issue with serving source maps.

> **_NOTE:_**  this problem stems from using the [deprecated `url.parse` instead of the newer URL](https://nodejs.org/api/url.html#urlparseurlstring-parsequerystring-slashesdenotehost).

Changelog: [General][Fixed] Metro supporting non-ASCII bundle/sourcemaps paths

Pull Request resolved: facebook#1538

Test Plan:
Using a test diff D78806803 I managed to reproduce Metro not launching RNTester before this diff.

1. `buck2 install -r rntester-android` (with the modified bundle path)
2. `DEV=1 js1 run`
3. launch `RNTester`

Before- app crashes:
 https://pxl.cl/7LFkb

After- app launches, debugging works:
{F1980565661}

can even add the bundle to ignore-list and then it gets ignored:
{F1980565660}

Differential Revision: D78799358
@facebook-github-bot
Copy link
Copy Markdown
Contributor

@vzaidman merged this pull request in 92ac74c.

@vzaidman
Copy link
Copy Markdown
Contributor

vzaidman commented Sep 1, 2025

Note

This PR was modified by @vzaidman and merged in 92ac74c with a more upstream decoding of URLs to prevent non-ASCII from crashing Metro.

However, while Metro would now indeed not crash, Metro doesn't fully support non-ASCII files as of this PR.

Instead, the later merged commit cb02cdb adds a comprehensive support to non-ASCII in Metro with tests.

The split into two PRs is intended to credit the author of this PR and to allow us to revert the latter more complex code without removing this fix.

Also see subsequent commits: 71e158a and 98badca

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Merged Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants