Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 57 additions & 5 deletions test/parallel/test-url-pathtofileurl.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,63 @@ const url = require('url');
}

{
assert.throws(() => {
url.pathToFileURL('\\\\exa mple\\share\\file.txt', { windows: true });
}, {
code: 'ERR_INVALID_URL',
});
const forbiddenHostnameChars = [
'\\\\exa mple\\share\\file.txt',
'\\\\host name\\share\\file.txt', // space
'\\\\host@name\\share\\file.txt', // at sign
'\\\\host:name\\share\\file.txt', // colon
'\\\\host[name\\share\\file.txt', // left bracket
'\\\\host]name\\share\\file.txt', // right bracket
];
Comment on lines +25 to +32
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to https://url.spec.whatwg.org/#host-miscellaneous, there are a few more forbidden char we might as well check for:

Suggested change
const forbiddenHostnameChars = [
'\\\\exa mple\\share\\file.txt',
'\\\\host name\\share\\file.txt', // space
'\\\\host#name\\share\\file.txt', // hash
'\\\\host?name\\share\\file.txt', // question mark
'\\\\host@name\\share\\file.txt', // at sign
'\\\\host:name\\share\\file.txt', // colon
'\\\\host/name\\share\\file.txt', // forward slash
'\\\\host[name\\share\\file.txt', // left bracket
'\\\\host]name\\share\\file.txt', // right bracket
];
const forbiddenHostnameChars = Array.from('\0\t\n\r #:<>?@[]^|', (sep) => `\\\\host${sep}name\\share\\file.txt`);

But it looks like \n, \r, \t are ignored instead of being rejected; # and ? might have a special significant in UNC not sure

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've opened ada-url/ada#1142 to address the # and ? cases

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will wait it to reach Node.js main, ping me please

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry forgot to follow up, but the upstream issue was closed so let's limit to the ones that are supported

Suggested change
const forbiddenHostnameChars = [
'\\\\exa mple\\share\\file.txt',
'\\\\host name\\share\\file.txt', // space
'\\\\host#name\\share\\file.txt', // hash
'\\\\host?name\\share\\file.txt', // question mark
'\\\\host@name\\share\\file.txt', // at sign
'\\\\host:name\\share\\file.txt', // colon
'\\\\host/name\\share\\file.txt', // forward slash
'\\\\host[name\\share\\file.txt', // left bracket
'\\\\host]name\\share\\file.txt', // right bracket
];
const forbiddenHostnameChars = Array.from('\0 :<>@[]^|', (sep) => `\\\\host${sep}name\\share\\file.txt`);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's why I sent 51f1a25. Honestly, it's much clearer to see that list than the approach you suggested.

for (const path of forbiddenHostnameChars) {
assert.throws(() => {
url.pathToFileURL(path, { windows: true });
}, {
code: 'ERR_INVALID_URL',
}, `pathToFileURL('${path}') should throw ERR_INVALID_URL`);
}
}

{
const hostnameStateTerminatorTestCases = [
{
path: '\\\\host#name\\share\\file.txt',
expected: 'file://host/share/file.txt',
},
{
path: '\\\\host?name\\share\\file.txt',
expected: 'file://host/share/file.txt',
},
{
path: '\\\\host/name\\share\\file.txt',
expected: 'file://host/share/file.txt',
},
];
for (const { path, expected } of hostnameStateTerminatorTestCases) {
const actual = url.pathToFileURL(path, { windows: true }).href;
assert.strictEqual(actual, expected);
}
}

{
const ignoredHostnameCodePointTestCases = [
{
path: '\\\\host\nname\\share\\file.txt',
expected: 'file://hostname/share/file.txt',
},
{
path: '\\\\host\rname\\share\\file.txt',
expected: 'file://hostname/share/file.txt',
},
{
path: '\\\\host\tname\\share\\file.txt',
expected: 'file://hostname/share/file.txt',
},
];
for (const { path, expected } of ignoredHostnameCodePointTestCases) {
const actual = url.pathToFileURL(path, { windows: true }).href;
assert.strictEqual(actual, expected);
}
}

{
Expand Down
Loading