From b93ced6f633fab2733b40aef2541582b00e053fb Mon Sep 17 00:00:00 2001 From: Matthias Einwag Date: Tue, 22 Sep 2020 23:12:51 -0700 Subject: Allow to use a Github Auth token for fetching releases This change allows to use a authorization token provided by Github in order to fetch metadata for a RA release. Using an authorization token prevents to get rate-limited in environments where lots of RA users use a shared client IP (e.g. behind a company NAT). The auth token is stored in `ExtensionContext.globalState`. As far as I could observe through testing with a local WSL2 environment that state is synced between an extension installed locally and a remote version. The change provides no explicit command to query for an auth token. However in case a download fails it will provide a retry option as well as an option to enter the auth token. This should be more discoverable for most users. Closes #3688 --- editors/code/src/main.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) (limited to 'editors/code/src/main.ts') diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index bd99d696a..8c1610570 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -173,7 +173,9 @@ async function bootstrapExtension(config: Config, state: PersistentState): Promi if (!shouldCheckForNewNightly) return; } - const release = await fetchRelease("nightly").catch((e) => { + const release = await performDownloadWithRetryDialog(async () => { + return await fetchRelease("nightly", state.githubToken); + }, state).catch((e) => { log.error(e); if (state.releaseId === undefined) { // Show error only for the initial download vscode.window.showErrorMessage(`Failed to download rust-analyzer nightly ${e}`); @@ -308,7 +310,10 @@ async function getServer(config: Config, state: PersistentState): Promise { + return await fetchRelease(releaseTag, state.githubToken); + }, state); const artifact = release.assets.find(artifact => artifact.name === `rust-analyzer-${platform}.gz`); assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); @@ -333,3 +338,49 @@ async function getServer(config: Config, state: PersistentState): Promise(downloadFunc: () => Promise, state: PersistentState): Promise { + while (true) { + try { + return await downloadFunc(); + } catch (e) { + let selected = await vscode.window.showErrorMessage("Failed perform download: " + e.message, {}, { + title: "Update Github Auth Token", + updateToken: true, + }, { + title: "Retry download", + retry: true, + }, { + title: "Dismiss", + }); + + if (selected?.updateToken) { + await queryForGithubToken(state); + continue; + } else if (selected?.retry) { + continue; + } + throw e; + }; + } + +} + +async function queryForGithubToken(state: PersistentState): Promise { + const githubTokenOptions: vscode.InputBoxOptions = { + value: state.githubToken, + password: true, + prompt: ` + This dialog allows to store a Github authorization token. + The usage of an authorization token allows will increase the rate + limit on the use of Github APIs and can thereby prevent getting + throttled. + Auth tokens can be obtained at https://github.com/settings/tokens`, + }; + + const newToken = await vscode.window.showInputBox(githubTokenOptions); + if (newToken) { + log.info("Storing new github token"); + await state.updateGithubToken(newToken); + } +} \ No newline at end of file -- cgit v1.2.3