Skip to content

Commit

Permalink
Remove unnecessary rawApi reading
Browse files Browse the repository at this point in the history
  • Loading branch information
goober committed Oct 23, 2020
1 parent 6579769 commit 15b57a1
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 172 deletions.
88 changes: 1 addition & 87 deletions packages/backend-common/src/reading/BitbucketUrlReader.test.ts
Expand Up @@ -19,8 +19,6 @@ import {
BitbucketUrlReader,
getApiRequestOptions,
getApiUrl,
getRawRequestOptions,
getRawUrl,
ProviderConfig,
readConfig,
} from './BitbucketUrlReader';
Expand Down Expand Up @@ -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: '' };
Expand Down Expand Up @@ -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: {
Expand All @@ -214,7 +130,6 @@ describe('BitbucketUrlReader', () => {
{
host: 'bitbucket.org',
apiBaseUrl: 'https://api.bitbucket.org/2.0',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
},
]);
});
Expand All @@ -225,7 +140,6 @@ describe('BitbucketUrlReader', () => {
{
host: 'bitbucket.org',
apiBaseUrl: 'https://api.bitbucket.org/2.0',
rawBaseUrl: 'https://api.bitbucket.org/2.0',
},
]);
});
Expand All @@ -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",
);
});

Expand Down
94 changes: 9 additions & 85 deletions packages/backend-common/src/reading/BitbucketUrlReader.ts
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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[] = [];

Expand All @@ -187,41 +125,33 @@ 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(/\/+$/, '');
} else if (host === 'bitbucket.org') {
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,
});
}

Expand All @@ -231,7 +161,6 @@ export function readConfig(config: Config): ProviderConfig[] {
providers.push({
host: 'bitbucket.org',
apiBaseUrl: DEFAULT_BASE_URL,
rawBaseUrl: DEFAULT_BASE_URL,
});
}

Expand All @@ -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 {
Expand Down

0 comments on commit 15b57a1

Please sign in to comment.