Path: blob/main/extensions/copilot/test/simulation/fixtures/doc-everywhere-issue-3763/githubServer.ts
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import fetch from 'cross-fetch';6import * as vscode from 'vscode';7import { GitHubServerType } from '../common/authentication';8import Logger from '../common/logger';9import { agent } from '../env/node/net';10import { getEnterpriseUri } from '../github/utils';11import { HostHelper } from './configuration';1213export class GitHubManager {14private static readonly _githubDotComServers = new Set<string>().add('github.com').add('ssh.github.com');15private static readonly _neverGitHubServers = new Set<string>().add('bitbucket.org').add('gitlab.com');16private _servers: Map<string, GitHubServerType> = new Map(Array.from(GitHubManager._githubDotComServers.keys()).map(key => [key, GitHubServerType.GitHubDotCom]));1718public static isGithubDotCom(host: string): boolean {19return this._githubDotComServers.has(host);20}2122public static isNeverGitHub(host: string): boolean {23return this._neverGitHubServers.has(host);24}2526public async isGitHub(host: vscode.Uri): Promise<GitHubServerType> {27if (host === null) {28return GitHubServerType.None;29}3031// .wiki/.git repos are not supported32if (host.path.endsWith('.wiki') || host.authority.match(/gist[.]github[.]com/)) {33return GitHubServerType.None;34}3536if (GitHubManager.isGithubDotCom(host.authority)) {37return GitHubServerType.GitHubDotCom;38}3940const knownEnterprise = getEnterpriseUri();41if ((host.authority.toLowerCase() === knownEnterprise?.authority.toLowerCase()) && (!this._servers.has(host.authority) || (this._servers.get(host.authority) === GitHubServerType.None))) {42return GitHubServerType.Enterprise;43}4445if (this._servers.has(host.authority)) {46return this._servers.get(host.authority) ?? GitHubServerType.None;47}4849const [uri, options] = await GitHubManager.getOptions(host, 'HEAD', '/rate_limit');5051let isGitHub = GitHubServerType.None;52try {53const response = await fetch(uri.toString(), options);54const otherGitHubHeaders: string[] = [];55response.headers.forEach((_value, header) => {56otherGitHubHeaders.push(header);57});58Logger.debug(`All headers: ${otherGitHubHeaders.join(', ')}`, 'GitHubServer');59const gitHubHeader = response.headers.get('x-github-request-id');60const gitHubEnterpriseHeader = response.headers.get('x-github-enterprise-version');61if (!gitHubHeader && !gitHubEnterpriseHeader) {62const [uriFallBack] = await GitHubManager.getOptions(host, 'HEAD', '/status');63const response = await fetch(uriFallBack.toString());64const responseText = await response.text();65if (responseText.startsWith('GitHub lives!')) {66// We've made it this far so it's not github.com67// It's very likely enterprise.68isGitHub = GitHubServerType.Enterprise;69} else {70// Check if we got an enterprise-looking needs auth response:71// { message: 'Must authenticate to access this API.', documentation_url: 'https://docs.github.com/enterprise/3.3/rest'}72Logger.appendLine(`Received fallback response from the server: ${responseText}`, 'GitHubServer');73const parsedResponse = JSON.parse(responseText);74if (parsedResponse.documentation_url && (parsedResponse.documentation_url as string).startsWith('https://docs.github.com/enterprise')) {75isGitHub = GitHubServerType.Enterprise;76}77}78} else {79isGitHub = ((gitHubHeader !== undefined) && (gitHubHeader !== null)) ? (gitHubEnterpriseHeader ? GitHubServerType.Enterprise : GitHubServerType.GitHubDotCom) : GitHubServerType.None;80}81return isGitHub;82} catch (ex) {83Logger.warn(`No response from host ${host}: ${ex.message}`, 'GitHubServer');84return isGitHub;85} finally {86Logger.debug(`Host ${host} is associated with GitHub: ${isGitHub}`, 'GitHubServer');87this._servers.set(host.authority, isGitHub);88}89}9091public static async getOptions(92hostUri: vscode.Uri,93method: string = 'GET',94path: string,95token?: string,96): Promise<[vscode.Uri, RequestInit]> {97const headers: {98'user-agent': string;99authorization?: string;100} = {101'user-agent': 'GitHub VSCode Pull Requests',102};103if (token) {104headers.authorization = `token ${token}`;105}106107const uri = vscode.Uri.joinPath(await HostHelper.getApiHost(hostUri), HostHelper.getApiPath(hostUri, path));108const requestInit = {109hostname: uri.authority,110port: 443,111method,112headers,113agent114};115116return [117uri,118requestInit as RequestInit,119];120}121}122123124