Remove unnecessary rawApi reading

This commit is contained in:
Mathias Åhsberg
2020-10-23 10:27:13 +02:00
parent 6579769dff
commit 15b57a1848
2 changed files with 10 additions and 172 deletions
@@ -19,8 +19,6 @@ import {
BitbucketUrlReader,
getApiRequestOptions,
getApiUrl,
getRawRequestOptions,
getRawUrl,
ProviderConfig,
readConfig,
} from './BitbucketUrlReader';
@@ -67,47 +65,6 @@ describe('BitbucketUrlReader', () => {
});
});
describe('getRawRequestOptions', () => {
it('inserts a token when needed', () => {
const withToken: ProviderConfig = {
host: '',
apiBaseUrl: '',
token: 'A',
};
const withoutToken: ProviderConfig = {
host: '',
apiBaseUrl: '',
};
expect(
(getRawRequestOptions(withToken).headers as any).Authorization,
).toEqual('Bearer A');
expect(
(getRawRequestOptions(withoutToken).headers as any).Authorization,
).toBeUndefined();
});
it('insert basic auth when needed', () => {
const withUsernameAndPassword: ProviderConfig = {
host: '',
apiBaseUrl: '',
username: 'some-user',
appPassword: 'my-secret',
};
const withoutUsernameAndPassword: ProviderConfig = {
host: '',
apiBaseUrl: '',
};
expect(
(getRawRequestOptions(withUsernameAndPassword).headers as any)
.Authorization,
).toEqual('Basic c29tZS11c2VyOm15LXNlY3JldA==');
expect(
(getRawRequestOptions(withoutUsernameAndPassword).headers as any)
.Authorization,
).toBeUndefined();
});
});
describe('getApiUrl', () => {
it('rejects targets that do not look like URLs', () => {
const config: ProviderConfig = { host: '', apiBaseUrl: '' };
@@ -147,47 +104,6 @@ describe('BitbucketUrlReader', () => {
});
});
describe('getRawUrl', () => {
it('rejects targets that do not look like URLs', () => {
const config: ProviderConfig = { host: '', apiBaseUrl: '' };
expect(() => getRawUrl('a/b', config)).toThrow(/Incorrect URL: a\/b/);
});
it('happy path for Bitbucket Cloud', () => {
const config: ProviderConfig = {
host: 'bitbucket.org',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
};
expect(
getRawUrl(
'https://bitbucket.org/org-name/repo-name/src/master/templates/my-template.yaml',
config,
),
).toEqual(
new URL(
'https://api.bitbucket.org/2.0/repositories/org-name/repo-name/src/master/templates/my-template.yaml',
),
);
});
it('happy path for Bitbucket Server', () => {
const config: ProviderConfig = {
host: 'bitbucket.mycompany.net',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
};
expect(
getRawUrl(
'https://bitbucket.mycompany.net/projects/a/repos/b/browse/path/to/c.yaml',
config,
),
).toEqual(
new URL(
'https://bitbucket.mycompany.net/rest/api/1.0/projects/a/repos/b/raw/path/to/c.yaml',
),
);
});
});
describe('readConfig', () => {
function config(
providers: {
@@ -214,7 +130,6 @@ describe('BitbucketUrlReader', () => {
{
host: 'bitbucket.org',
apiBaseUrl: 'https://api.bitbucket.org/2.0',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
},
]);
});
@@ -225,7 +140,6 @@ describe('BitbucketUrlReader', () => {
{
host: 'bitbucket.org',
apiBaseUrl: 'https://api.bitbucket.org/2.0',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
},
]);
});
@@ -234,7 +148,7 @@ describe('BitbucketUrlReader', () => {
expect(() =>
readConfig(config([{ host: 'bitbucket.mycompany.net' }])),
).toThrow(
"Bitbucket integration for 'bitbucket.mycompany.net' must configure an explicit apiBaseUrl and rawBaseUrl",
"Bitbucket integration for 'bitbucket.mycompany.net' must configure an explicit apiBaseUrl",
);
});
@@ -42,17 +42,6 @@ export type ProviderConfig = {
*/
apiBaseUrl?: string;
/**
* The base URL of the raw fetch endpoint of this provider, e.g.
* "https://api.bitbucket.org/2.0", with no trailing slash.
*
* May be omitted specifically for Bitbucket Cloud; then it will be deduced.
*
* The API will always be preferred if both its base URL and a token are
* present.
*/
rawBaseUrl?: string;
/**
* The authorization token to use for requests to a Bitbucket Server provider.
*
@@ -92,22 +81,6 @@ export function getApiRequestOptions(provider: ProviderConfig): RequestInit {
};
}
export function getRawRequestOptions(provider: ProviderConfig): RequestInit {
const headers: HeadersInit = {};
if (provider.token) {
headers.Authorization = `Bearer ${provider.token}`;
} else if (provider.username && provider.appPassword) {
headers.Authorization = `Basic ${Buffer.from(
`${provider.username}:${provider.appPassword}`,
'utf8',
).toString('base64')}`;
}
return {
headers,
};
}
// Converts for example
// from: https://bitbucket.org/orgname/reponame/src/master/file.yaml
// to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml
@@ -142,41 +115,6 @@ export function getApiUrl(target: string, provider: ProviderConfig): URL {
}
}
// Converts for example
// from: https://bitbucket.org/orgname/reponame/src/master/file.yaml
// to: https://api.bitbucket.org/2.0/repositories/orgname/reponame/src/master/file.yaml
export function getRawUrl(target: string, provider: ProviderConfig): URL {
try {
const { owner, name, ref, filepathtype, filepath } = parseGitUri(target);
if (
!owner ||
!name ||
(filepathtype !== 'browse' &&
filepathtype !== 'raw' &&
filepathtype !== 'src')
) {
throw new Error('Invalid Bitbucket URL or file path');
}
const pathWithoutSlash = filepath.replace(/^\//, '');
if (provider.host === 'bitbucket.org') {
if (!ref) {
throw new Error('Invalid Bitbucket URL or file path');
}
return new URL(
`${provider.rawBaseUrl}/repositories/${owner}/${name}/src/${ref}/${pathWithoutSlash}`,
);
}
return new URL(
`${provider.rawBaseUrl}/projects/${owner}/repos/${name}/raw/${pathWithoutSlash}?at=${ref}`,
);
} catch (e) {
throw new Error(`Incorrect URL: ${target}, ${e}`);
}
}
export function readConfig(config: Config): ProviderConfig[] {
const providers: ProviderConfig[] = [];
@@ -187,10 +125,9 @@ export function readConfig(config: Config): ProviderConfig[] {
for (const providerConfig of providerConfigs) {
const host = providerConfig.getOptionalString('host') ?? 'bitbucket.org';
let apiBaseUrl = providerConfig.getOptionalString('apiBaseUrl');
let rawBaseUrl = providerConfig.getOptionalString('rawBaseUrl');
const token = providerConfig.getOptionalString('token');
const username = providerConfig.getOptionalString('username');
const password = providerConfig.getOptionalString('appPassword');
const appPassword = providerConfig.getOptionalString('appPassword');
if (apiBaseUrl) {
apiBaseUrl = apiBaseUrl.replace(/\/+$/, '');
@@ -198,30 +135,23 @@ export function readConfig(config: Config): ProviderConfig[] {
apiBaseUrl = DEFAULT_BASE_URL;
}
if (rawBaseUrl) {
rawBaseUrl = rawBaseUrl.replace(/\/+$/, '');
} else if (host === 'bitbucket.org') {
rawBaseUrl = DEFAULT_BASE_URL;
}
if (!apiBaseUrl && !rawBaseUrl) {
if (!apiBaseUrl) {
throw new Error(
`Bitbucket integration for '${host}' must configure an explicit apiBaseUrl and rawBaseUrl`,
`Bitbucket integration for '${host}' must configure an explicit apiBaseUrl`,
);
}
if (!token && username && !password) {
if (!token && username && !appPassword) {
throw new Error(
`Bitbucket integration for '${host}' has configured a username but is missing a required password.`,
`Bitbucket integration for '${host}' has configured a username but is missing a required appPassword.`,
);
}
providers.push({
host,
apiBaseUrl,
rawBaseUrl,
token,
username,
appPassword: password,
appPassword,
});
}
@@ -231,7 +161,6 @@ export function readConfig(config: Config): ProviderConfig[] {
providers.push({
host: 'bitbucket.org',
apiBaseUrl: DEFAULT_BASE_URL,
rawBaseUrl: DEFAULT_BASE_URL,
});
}
@@ -258,14 +187,9 @@ export class BitbucketUrlReader implements UrlReader {
}
async read(url: string): Promise<Buffer> {
const useApi =
this.config.apiBaseUrl && (this.config.token || !this.config.rawBaseUrl);
const bitbucketUrl = useApi
? getApiUrl(url, this.config)
: getRawUrl(url, this.config);
const options = useApi
? getApiRequestOptions(this.config)
: getRawRequestOptions(this.config);
const bitbucketUrl = getApiUrl(url, this.config);
const options = getApiRequestOptions(this.config);
let response: Response;
try {