-
Notifications
You must be signed in to change notification settings - Fork 2k
fix: gRPC oauth2 call is not taking ssl cert and proxy config #6313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis PR refactors OAuth2 handling in gRPC request processing by extracting it into a centralized Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/bruno-electron/src/ipc/network/cert-utils.js(1 hunks)packages/bruno-electron/src/ipc/network/grpc-event-handlers.js(3 hunks)packages/bruno-electron/src/ipc/network/prepare-grpc-request.js(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (CODING_STANDARDS.md)
**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation, never tabs
Use single quotes for strings instead of double quotes
Always add semicolons at the end of statements
No trailing commas in code
Always use parentheses around parameters in arrow functions, even for single parameters
For multiline constructs, put opening braces on the same line with a minimum of 2 elements for multiline formatting
No newlines inside function parentheses
Space before and after the arrow in arrow functions:() => {}
No space between function name and parentheses:func()notfunc ()
Semicolons should go at the end of the line, not on a new line
Function names should be concise and descriptive
Add JSDoc comments to provide details to abstractions
Avoid single-line abstractions where all that is being done is increasing the call stack with one additional function
Add meaningful comments to explain complex code flow instead of obvious comments
Files:
packages/bruno-electron/src/ipc/network/cert-utils.jspackages/bruno-electron/src/ipc/network/grpc-event-handlers.jspackages/bruno-electron/src/ipc/network/prepare-grpc-request.js
🧠 Learnings (2)
📓 Common learnings
Learnt from: bijin-bruno
Repo: usebruno/bruno PR: 6263
File: packages/bruno-requests/src/auth/oauth2-helper.ts:249-249
Timestamp: 2025-12-02T07:24:50.299Z
Learning: In OAuth2 Basic Auth headers for Bruno, clientSecret is optional and can be omitted. When constructing the Authorization header in `packages/bruno-requests/src/auth/oauth2-helper.ts`, use `clientSecret || ''` instead of `clientSecret!` to properly handle cases where only clientId is provided, per community requests.
📚 Learning: 2025-12-02T07:24:50.299Z
Learnt from: bijin-bruno
Repo: usebruno/bruno PR: 6263
File: packages/bruno-requests/src/auth/oauth2-helper.ts:249-249
Timestamp: 2025-12-02T07:24:50.299Z
Learning: In OAuth2 Basic Auth headers for Bruno, clientSecret is optional and can be omitted. When constructing the Authorization header in `packages/bruno-requests/src/auth/oauth2-helper.ts`, use `clientSecret || ''` instead of `clientSecret!` to properly handle cases where only clientId is provided, per community requests.
Applied to files:
packages/bruno-electron/src/ipc/network/prepare-grpc-request.js
🧬 Code graph analysis (1)
packages/bruno-electron/src/ipc/network/cert-utils.js (1)
packages/bruno-cli/src/runner/run-single-request.js (2)
hostRegex(76-76)hostRegex(261-261)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: SSL Tests - Linux
- GitHub Check: SSL Tests - macOS
- GitHub Check: SSL Tests - Windows
- GitHub Check: Unit Tests
- GitHub Check: Playwright E2E Tests
- GitHub Check: CLI Tests
🔇 Additional comments (5)
packages/bruno-electron/src/ipc/network/cert-utils.js (1)
70-70: Good defensive guard.The null check prevents potential runtime errors when
requestUrlis undefined or null before calling.match().packages/bruno-electron/src/ipc/network/prepare-grpc-request.js (1)
127-127: LGTM on named export.The named export for
configureRequestproperly extends the module's public API while maintaining backward compatibility with the default export.packages/bruno-electron/src/ipc/network/grpc-event-handlers.js (3)
11-11: LGTM on import.The import correctly destructures the named export from
prepare-grpc-request.
57-66: Correct integration of OAuth2 configuration.The
configureRequestcall is properly placed after request preparation and certificate configuration, with correct parameter passing and awaiting.
205-214: Consistent OAuth2 configuration in reflection handler.The
configureRequestintegration follows the same correct pattern as the start-connection handler.
| const configureRequest = async (grpcRequest, request, collection, envVars, runtimeVariables, processEnvVars, promptVariables, certsAndProxyConfig) => { | ||
| if (grpcRequest.oauth2) { | ||
| let requestCopy = cloneDeep(grpcRequest); | ||
| const { oauth2: { grantType, tokenPlacement, tokenHeaderPrefix, tokenQueryKey } = {} } = requestCopy || {}; | ||
| let credentials, credentialsId, oauth2Url, debugInfo; | ||
| switch (grantType) { | ||
| case 'authorization_code': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| case 'client_credentials': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| case 'password': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empty catch blocks silently swallow URL parsing errors.
Lines 33, 47, and 61 have empty catch blocks that suppress any errors from URL parsing. This could hide configuration issues or invalid URLs, making debugging difficult.
Apply this diff to log errors:
} else {
try {
const url = new URL(grpcRequest.url);
url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
grpcRequest.url = url?.toString();
- } catch (error) { }
+ } catch (error) {
+ console.error('Failed to parse URL for OAuth2 token placement:', error);
+ }
}Apply similar changes to the other two catch blocks at lines 47 and 61.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const configureRequest = async (grpcRequest, request, collection, envVars, runtimeVariables, processEnvVars, promptVariables, certsAndProxyConfig) => { | |
| if (grpcRequest.oauth2) { | |
| let requestCopy = cloneDeep(grpcRequest); | |
| const { oauth2: { grantType, tokenPlacement, tokenHeaderPrefix, tokenQueryKey } = {} } = requestCopy || {}; | |
| let credentials, credentialsId, oauth2Url, debugInfo; | |
| switch (grantType) { | |
| case 'authorization_code': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| case 'client_credentials': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| case 'password': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| } | |
| } | |
| }; | |
| const configureRequest = async (grpcRequest, request, collection, envVars, runtimeVariables, processEnvVars, promptVariables, certsAndProxyConfig) => { | |
| if (grpcRequest.oauth2) { | |
| let requestCopy = cloneDeep(grpcRequest); | |
| const { oauth2: { grantType, tokenPlacement, tokenHeaderPrefix, tokenQueryKey } = {} } = requestCopy || {}; | |
| let credentials, credentialsId, oauth2Url, debugInfo; | |
| switch (grantType) { | |
| case 'authorization_code': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { | |
| console.error('Failed to parse URL for OAuth2 token placement:', error); | |
| } | |
| } | |
| break; | |
| case 'client_credentials': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { | |
| console.error('Failed to parse URL for OAuth2 token placement:', error); | |
| } | |
| } | |
| break; | |
| case 'password': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { | |
| console.error('Failed to parse URL for OAuth2 token placement:', error); | |
| } | |
| } | |
| break; | |
| } | |
| } | |
| }; |
🤖 Prompt for AI Agents
In packages/bruno-electron/src/ipc/network/prepare-grpc-request.js around lines
16 to 66, the three empty catch blocks at ~lines 33, 47 and 61 silently swallow
URL parsing errors; update each catch to log the error (and the grpcRequest.url
or tokenQueryKey/context) instead of being empty so configuration/invalid-URL
issues are visible — use the module's logger (e.g. processLogger.error) if
available otherwise console.error, include a short message plus the caught error
and the URL being parsed, and keep the original behavior (don’t rethrow) so
token placement still falls back to the URL not being modified.
| switch (grantType) { | ||
| case 'authorization_code': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| case 'client_credentials': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| case 'password': | ||
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { | ||
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | ||
| } else { | ||
| try { | ||
| const url = new URL(grpcRequest.url); | ||
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | ||
| grpcRequest.url = url?.toString(); | ||
| } catch (error) { } | ||
| } | ||
| break; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Extract duplicated token placement logic.
The token placement logic (lines 26-34, 40-48, 54-62) is duplicated across all three grant type cases. Only the OAuth2 token fetching differs between cases.
Extract the common logic into a helper function:
+const placeOAuth2Token = (grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey) => {
+ if (tokenPlacement === 'header') {
+ grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
+ } else {
+ try {
+ const url = new URL(grpcRequest.url);
+ url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
+ grpcRequest.url = url?.toString();
+ } catch (error) {
+ console.error('Failed to parse URL for OAuth2 token placement:', error);
+ }
+ }
+};
+
const configureRequest = async (grpcRequest, request, collection, envVars, runtimeVariables, processEnvVars, promptVariables, certsAndProxyConfig) => {
if (grpcRequest.oauth2) {
let requestCopy = cloneDeep(grpcRequest);
const { oauth2: { grantType, tokenPlacement, tokenHeaderPrefix, tokenQueryKey } = {} } = requestCopy || {};
let credentials, credentialsId, oauth2Url, debugInfo;
switch (grantType) {
case 'authorization_code':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables);
({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig }));
grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid };
- if (tokenPlacement == 'header') {
- grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
- } else {
- try {
- const url = new URL(grpcRequest.url);
- url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
- grpcRequest.url = url?.toString();
- } catch (error) { }
- }
+ placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey);
break;
case 'client_credentials':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables);
({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig }));
grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid };
- if (tokenPlacement == 'header') {
- grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
- } else {
- try {
- const url = new URL(grpcRequest.url);
- url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
- grpcRequest.url = url?.toString();
- } catch (error) { }
- }
+ placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey);
break;
case 'password':
interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables);
({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig }));
grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid };
- if (tokenPlacement == 'header') {
- grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`;
- } else {
- try {
- const url = new URL(grpcRequest.url);
- url?.searchParams?.set(tokenQueryKey, credentials?.access_token);
- grpcRequest.url = url?.toString();
- } catch (error) { }
- }
+ placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey);
break;
}
}
};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| switch (grantType) { | |
| case 'authorization_code': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| case 'client_credentials': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| case 'password': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| if (tokenPlacement == 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { } | |
| } | |
| break; | |
| } | |
| const placeOAuth2Token = (grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey) => { | |
| if (tokenPlacement === 'header') { | |
| grpcRequest.headers['Authorization'] = `${tokenHeaderPrefix} ${credentials?.access_token}`; | |
| } else { | |
| try { | |
| const url = new URL(grpcRequest.url); | |
| url?.searchParams?.set(tokenQueryKey, credentials?.access_token); | |
| grpcRequest.url = url?.toString(); | |
| } catch (error) { | |
| console.error('Failed to parse URL for OAuth2 token placement:', error); | |
| } | |
| } | |
| }; | |
| const configureRequest = async (grpcRequest, request, collection, envVars, runtimeVariables, processEnvVars, promptVariables, certsAndProxyConfig) => { | |
| if (grpcRequest.oauth2) { | |
| let requestCopy = cloneDeep(grpcRequest); | |
| const { oauth2: { grantType, tokenPlacement, tokenHeaderPrefix, tokenQueryKey } = {} } = requestCopy || {}; | |
| let credentials, credentialsId, oauth2Url, debugInfo; | |
| switch (grantType) { | |
| case 'authorization_code': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey); | |
| break; | |
| case 'client_credentials': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingClientCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey); | |
| break; | |
| case 'password': | |
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | |
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingPasswordCredentials({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | |
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | |
| placeOAuth2Token(grpcRequest, credentials, tokenPlacement, tokenHeaderPrefix, tokenQueryKey); | |
| break; | |
| } | |
| } | |
| }; |
🤖 Prompt for AI Agents
In packages/bruno-electron/src/ipc/network/prepare-grpc-request.js around lines
21 to 64, the token placement logic (setting grpcRequest.oauth2Credentials and
placing the access token into either the Authorization header or URL query) is
duplicated in each grant_type case; extract this into a single helper function
that accepts the grpcRequest, credentials, oauth2Url, credentialsId, debugInfo,
tokenPlacement, tokenHeaderPrefix, tokenQueryKey and original request (for
folderUid) and performs: set grpcRequest.oauth2Credentials with folderUid, then
if tokenPlacement === 'header' set grpcRequest.headers['Authorization'] to
`${tokenHeaderPrefix} ${credentials?.access_token}`, else try to append
credentials?.access_token to the grpcRequest.url search params (preserving the
current silent error behavior). Replace the duplicated blocks in each case with
a call to this helper after fetching credentials (keeping the existing
interpolateVars and token fetch calls intact).
| interpolateVars(requestCopy, envVars, runtimeVariables, processEnvVars, promptVariables); | ||
| ({ credentials, url: oauth2Url, credentialsId, debugInfo } = await getOAuth2TokenUsingAuthorizationCode({ request: requestCopy, collectionUid: collection.uid, certsAndProxyConfig })); | ||
| grpcRequest.oauth2Credentials = { credentials, url: oauth2Url, collectionUid: collection.uid, credentialsId, debugInfo, folderUid: request.oauth2Credentials?.folderUid }; | ||
| if (tokenPlacement == 'header') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use strict equality operators.
Lines 26, 40, and 54 use loose equality (==) instead of strict equality (===). As per coding guidelines, always use strict equality to avoid type coercion issues.
Apply this diff:
- if (tokenPlacement == 'header') {
+ if (tokenPlacement === 'header') {Apply the same change to lines 40 and 54.
Also applies to: 40-40, 54-54
🤖 Prompt for AI Agents
In packages/bruno-electron/src/ipc/network/prepare-grpc-request.js around lines
26, 40, and 54, the code uses loose equality (==) for comparisons; replace those
with strict equality (===) at each occurrence to avoid type coercion issues and
conform to project coding guidelines. Ensure you update the three comparisons at
lines 26, 40, and 54 to use === and run lint/tests to confirm no other
occurrences remain.
Description
Contribution Checklist:
Note: Keeping the PR small and focused helps make it easier to review and merge. If you have multiple changes you want to make, please consider submitting them as separate pull requests.
Publishing to New Package Managers
Please see here for more information.
Summary by CodeRabbit
Bug Fixes
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.