fix: grpc import paths (#6726)

* fix: grpc import paths

* refactor: extract protobuf include directory logic into a separate function

* rm: comment

* fix: improve filtering of enabled import paths in protobuf configuration

* refactor: streamline import path handling in protobuf configuration
This commit is contained in:
sanish chirayath
2026-01-08 21:16:47 +05:30
committed by GitHub
parent 58a38ac5a1
commit b01b8d7bc4
3 changed files with 38 additions and 27 deletions

View File

@@ -1,6 +1,3 @@
import cloneDeep from 'lodash/cloneDeep';
import { resolvePath } from 'utils/filesystem';
export const sendNetworkRequest = async (item, collection, environment, runtimeVariables) => {
return new Promise((resolve, reject) => {
if (['http-request', 'graphql-request'].includes(item.type)) {
@@ -143,25 +140,10 @@ export const endGrpcStream = async (requestId) => {
};
export const loadGrpcMethodsFromProtoFile = async (filePath, collection = null) => {
return new Promise(async (resolve, reject) => {
return new Promise((resolve, reject) => {
const { ipcRenderer } = window;
// Extract import paths from collection's gRPC config if available
let importPaths = [];
if (collection) {
const config = cloneDeep(collection.brunoConfig);
if (config.protobuf && config.protobuf.importPaths) {
// Use Promise.all to wait for all resolvePath calls to complete
const enabledImportPaths = config.protobuf.importPaths.filter((importPath) => importPath.enabled);
importPaths = await Promise.all(enabledImportPaths.map((importPath) => {
return resolvePath(importPath.path, collection.pathname);
}));
}
}
ipcRenderer.invoke('grpc:load-methods-proto', { filePath, includeDirs: importPaths }).then(resolve).catch(reject);
ipcRenderer.invoke('grpc:load-methods-proto', { filePath, collection }).then(resolve).catch(reject);
});
};

View File

@@ -8,11 +8,30 @@ const { getCertsAndProxyConfig } = require('./cert-utils');
const { interpolateString } = require('./interpolate-string');
const path = require('node:path');
const prepareGrpcRequest = require('./prepare-grpc-request');
const { normalizeAndResolvePath } = require('../../utils/filesystem');
const { configureRequest } = require('./prepare-grpc-request');
// Creating grpcClient at module level so it can be accessed from window-all-closed event
let grpcClient;
/**
* Extract protobuf include directories from collection config
* @param {Object} collection - The collection object
* @returns {string[]} Array of resolved include directory paths
*/
const getProtobufIncludeDirs = (collection) => {
if (!collection) {
return [];
}
const brunoConfig = collection.draft?.brunoConfig || collection.brunoConfig;
const importPaths = brunoConfig?.protobuf?.importPaths ?? [];
return importPaths
.filter(({ enabled }) => Boolean(enabled))
.map(({ path: relativePath }) => normalizeAndResolvePath(path.resolve(collection.pathname, relativePath)));
};
/**
* Register IPC handlers for gRPC
*/
@@ -89,6 +108,9 @@ const registerGrpcEventHandlers = (window) => {
body: preparedRequest.body,
timestamp: Date.now()
};
const includeDirs = getProtobufIncludeDirs(collection);
// Start gRPC connection with the processed request and certificates
await grpcClient.startConnection({
request: preparedRequest,
@@ -98,7 +120,8 @@ const registerGrpcEventHandlers = (window) => {
certificateChain,
passphrase,
pfx,
verifyOptions
verifyOptions,
includeDirs
});
sendEvent('grpc:request', preparedRequest.uid, collection.uid, requestSent);
@@ -260,8 +283,10 @@ const registerGrpcEventHandlers = (window) => {
});
// Load methods from proto file
ipcMain.handle('grpc:load-methods-proto', async (event, { filePath, includeDirs }) => {
ipcMain.handle('grpc:load-methods-proto', async (event, { filePath, collection }) => {
try {
const includeDirs = getProtobufIncludeDirs(collection);
const methods = await grpcClient.loadMethodsFromProtoFile(filePath, includeDirs);
return { success: true, methods: safeParseJSON(safeStringifyJSON(methods)) };
} catch (error) {

View File

@@ -316,10 +316,11 @@ class GrpcClient {
* @param {string} [options.collectionUid] - Collection UID
* @param {Object} [options.certificates] - Certificate configuration
* @param {Object} [options.verifyOptions] - Additional options for verifying the server certificate
* @param {string[]} [options.includeDirs] - Include directories for proto file resolution
* @returns {Promise<boolean>} Whether methods were successfully refreshed
* @private
*/
async #refreshMethods({ url, headers, protoPath, collectionPath, collectionUid, certificates = {}, verifyOptions }) {
async #refreshMethods({ url, headers, protoPath, collectionPath, collectionUid, certificates = {}, verifyOptions, includeDirs = [] }) {
try {
// Try reflection first if no proto path is specified
if (!protoPath) {
@@ -339,8 +340,8 @@ class GrpcClient {
// Try proto file if available
if (protoPath) {
const absoluteProtoPath = nodePath.join(collectionPath, protoPath);
await this.loadMethodsFromProtoFile(absoluteProtoPath, []);
const absoluteProtoPath = nodePath.resolve(collectionPath, protoPath);
await this.loadMethodsFromProtoFile(absoluteProtoPath, includeDirs);
return true;
}
@@ -463,6 +464,7 @@ class GrpcClient {
* @param {string} [params.pfx] - The PFX/P12 certificate data
* @param {Object} [params.verifyOptions] - Additional options for verifying the server certificate
* @param {import('@grpc/grpc-js').ChannelOptions} [params.channelOptions] - Additional options for the gRPC channel
* @param {string[]} [params.includeDirs] - Include directories for proto file resolution
*/
async startConnection({
request,
@@ -473,7 +475,8 @@ class GrpcClient {
passphrase,
pfx,
verifyOptions,
channelOptions = {}
channelOptions = {},
includeDirs = []
}) {
const credentials = this.#getChannelCredentials({
url: request.url,
@@ -509,7 +512,8 @@ class GrpcClient {
passphrase,
pfx
},
verifyOptions
verifyOptions,
includeDirs
});
if (!refreshSuccess) {