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