Try to encode authority for asWebviewUri

Fixes #123494

This change attempts to address issues where `asWebviewUri` could create an valid uri but an invalid http uri. This issue appears to be when the host contains a forbidden character (even if it is percent encoded): https://url.spec.whatwg.org/#forbidden-host-code-point

Having one of these characters in the host causes the url to become invalid, resulting in network requests never being made

To fix this, I've added a very simple (poor) encoding mechanism for the authority. I went with my own mechanism over something like base64 because base64 can output `/` and it's also not easy to use across both node and browsers. I also considered base62 and punycode, but both of these would be best to pull in libraries for
This commit is contained in:
Matt Bierner
2021-08-07 00:19:57 -07:00
parent 813c0b2178
commit 649dd18019
3 changed files with 49 additions and 5 deletions

View File

@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { CharCode } from 'vs/base/common/charCode';
import { Schemas } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import type * as vscode from 'vscode';
@@ -57,9 +58,27 @@ export function asWebviewUri(
return URI.from({
scheme: Schemas.https,
authority: `${resource.scheme}+${resource.authority}.${webviewRootResourceAuthority}`,
authority: `${resource.scheme}+${encodeAuthority(resource.authority)}.${webviewRootResourceAuthority}`,
path: resource.path,
fragment: resource.fragment,
query: resource.query,
});
}
function encodeAuthority(authority: string): string {
return authority.replace(/./g, char => {
const code = char.charCodeAt(0);
if (
(code >= CharCode.a && code <= CharCode.z)
|| (code >= CharCode.A && code <= CharCode.Z)
|| (code >= CharCode.Digit0 && code <= CharCode.Digit9)
) {
return char;
}
return '-' + code.toString(16).padStart(4, '0');
});
}
export function decodeAuthority(authority: string) {
return authority.replace(/-([0-9a-f]{4})/g, (_, code) => String.fromCharCode(parseInt(code, 16)));
}