Skip to content

Commit fc00457

Browse files
committed
Introduce BitbucketHttpError to redact more effectively
1 parent 521cc54 commit fc00457

File tree

4 files changed

+40
-38
lines changed

4 files changed

+40
-38
lines changed

components/server/src/bitbucket-server/bitbucket-server-context-parser.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { AbstractContextParser, IContextParser, URLParts } from "../workspace/co
1313
import { URL } from "url";
1414
import { BitbucketServer, BitbucketServerApi } from "./bitbucket-server-api";
1515
import { BitbucketServerTokenHelper } from "./bitbucket-server-token-handler";
16+
import { handleBitbucketError } from "./utils";
1617

1718
const DEFAULT_BRANCH = "master";
1819

@@ -87,11 +88,8 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
8788

8889
return await this.handleNavigatorContext(ctx, user, repoKind, host, owner, repoName, more);
8990
} catch (e) {
90-
span.addTags({ contextUrl }).log({ error: e });
91-
let error = e;
92-
if (e.name === "HTTPError") {
93-
error = e.status; // we don't want to expose the full error message since it contains credentials
94-
}
91+
const error = e instanceof Error ? handleBitbucketError(e) : e;
92+
span.addTags({ contextUrl }).log({ error });
9593
log.error({ userId: user.id }, "Error parsing Bitbucket context", error);
9694
throw e;
9795
} finally {
@@ -274,11 +272,8 @@ export class BitbucketServerContextParser extends AbstractContextParser implemen
274272
repository,
275273
};
276274
} catch (e) {
277-
span.log({ error: e });
278-
let error = e;
279-
if (e.name === "HTTPError") {
280-
error = e.status; // we don't want to expose the full error message since it contains credentials
281-
}
275+
const error = e instanceof Error ? handleBitbucketError(e) : e;
276+
span.log({ error });
282277
log.error({ userId: user.id }, "Error parsing Bitbucket navigator request context", error);
283278
throw e;
284279
} finally {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright (c) 2024 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { HTTPError } from "bitbucket/src/error/types";
8+
9+
export class BitbucketHttpError extends Error {
10+
status: number;
11+
constructor(originalErr: HTTPError, message: string) {
12+
if (originalErr.request?.headers.authorization) {
13+
originalErr.request.headers.authorization = "<redacted>";
14+
}
15+
super(message);
16+
}
17+
}
18+
19+
export function handleBitbucketError(err: Error): Error {
20+
return err instanceof HTTPError ? new BitbucketHttpError(err, "Error parsing BB context") : err;
21+
}

components/server/src/bitbucket/bitbucket-context-parser.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { NotFoundError } from "../errors";
2020
import { AbstractContextParser, IContextParser, IssueContexts } from "../workspace/context-parser";
2121
import { BitbucketApiFactory } from "./bitbucket-api-factory";
2222
import { BitbucketTokenHelper } from "./bitbucket-token-handler";
23+
import { handleBitbucketError } from "../bitbucket-server/utils";
2324

2425
const DEFAULT_BRANCH = "master";
2526

@@ -103,11 +104,8 @@ export class BitbucketContextParser extends AbstractContextParser implements ICo
103104
}
104105
return await this.handleNavigatorContext(ctx, user, host, owner, repoName);
105106
} catch (e) {
106-
span.addTags({ contextUrl }).log({ error: e });
107-
let error = e;
108-
if (e.name === "HTTPError") {
109-
error = e.status; // we don't want to expose the full error message since it contains credentials
110-
}
107+
const error = e instanceof Error ? handleBitbucketError(e) : e;
108+
span.addTags({ contextUrl }).log({ error });
111109
log.error({ userId: user.id }, "Error parsing Bitbucket context", error);
112110
throw e;
113111
} finally {
@@ -214,11 +212,8 @@ export class BitbucketContextParser extends AbstractContextParser implements ICo
214212
repository,
215213
} as NavigatorContext;
216214
} catch (e) {
215+
const error = e instanceof Error ? handleBitbucketError(e) : e;
217216
span.log({ error: e });
218-
let error = e;
219-
if (e.name === "HTTPError") {
220-
error = e.status; // we don't want to expose the full error message since it contains credentials
221-
}
222217
log.error({ userId: user.id }, "Error parsing Bitbucket navigator request context", error);
223218
throw e;
224219
} finally {
@@ -279,11 +274,8 @@ export class BitbucketContextParser extends AbstractContextParser implements ICo
279274
owner,
280275
};
281276
} catch (e) {
282-
span.log({ error: e });
283-
let error = e;
284-
if (e.name === "HTTPError") {
285-
error = e.status; // we don't want to expose the full error message since it contains credentials
286-
}
277+
const error = e instanceof Error ? handleBitbucketError(e) : e;
278+
span.log({ error });
287279
log.error({ userId: user.id }, "Error parsing Bitbucket pull request context", error);
288280
throw e;
289281
} finally {
@@ -315,11 +307,8 @@ export class BitbucketContextParser extends AbstractContextParser implements ICo
315307
localBranch: IssueContexts.toBranchName(user, more.title, more.nr),
316308
};
317309
} catch (e) {
318-
span.log({ error: e });
319-
let error = e;
320-
if (e.name === "HTTPError") {
321-
error = e.status; // we don't want to expose the full error message since it contains credentials
322-
}
310+
const error = e instanceof Error ? handleBitbucketError(e) : e;
311+
span.log({ error });
323312
log.error({ userId: user.id }, "Error parsing Bitbucket issue context", error);
324313
throw e;
325314
} finally {

components/server/src/bitbucket/bitbucket-file-provider.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
99
import { inject, injectable } from "inversify";
1010
import { FileProvider, MaybeContent, RevisionNotFoundError } from "../repohost/file-provider";
1111
import { BitbucketApiFactory } from "./bitbucket-api-factory";
12+
import { handleBitbucketError } from "../bitbucket-server/utils";
1213

1314
@injectable()
1415
export class BitbucketFileProvider implements FileProvider {
@@ -47,16 +48,14 @@ export class BitbucketFileProvider implements FileProvider {
4748

4849
return lastCommit;
4950
} catch (err) {
50-
if (err.status && err.status === 404) {
51+
const error = err instanceof Error ? handleBitbucketError(err) : err;
52+
if (error.status && error.status === 404) {
5153
throw new RevisionNotFoundError(
5254
`File ${path} does not exist in repository ${repository.owner}/${repository.name}`,
5355
);
5456
}
5557

56-
if (err.name === "HTTPError") {
57-
err = err.status; // we don't want to expose the full error message since it contains credentials
58-
}
59-
log.error({ userId: user.id }, err);
58+
log.error({ userId: user.id }, error);
6059
throw new Error(`Could not fetch ${path} of repository ${repository.owner}/${repository.name}: ${err}`);
6160
}
6261
}
@@ -79,10 +78,8 @@ export class BitbucketFileProvider implements FileProvider {
7978
).data;
8079
return contents as string;
8180
} catch (err) {
82-
if (err.name === "HTTPError") {
83-
err = err.status; // we don't want to expose the full error message since it contains credentials
84-
}
85-
log.debug({ userId: user.id }, err);
81+
const error = err instanceof Error ? handleBitbucketError(err) : err;
82+
log.debug({ userId: user.id }, error);
8683
}
8784
}
8885
}

0 commit comments

Comments
 (0)