From 1bf47039d1d7b16d68ea5f6b4ba00ef6363b1c63 Mon Sep 17 00:00:00 2001 From: Siddharth Gelera Date: Mon, 15 Sep 2025 18:56:44 +0530 Subject: [PATCH] fix: fix header movement and minor cleanup --- .../RequestPane/WSSettingsPane/index.js | 2 +- .../RequestPane/WsQueryUrl/index.js | 2 +- packages/bruno-app/src/utils/network/index.js | 24 ++-- .../src/ipc/network/ws-event-handlers.js | 125 +++--------------- packages/bruno-requests/src/network/index.ts | 1 - .../bruno-requests/src/network/ws-request.ts | 65 --------- packages/bruno-requests/src/ws/ws-client.js | 26 +--- 7 files changed, 34 insertions(+), 211 deletions(-) delete mode 100644 packages/bruno-requests/src/network/ws-request.ts diff --git a/packages/bruno-app/src/components/RequestPane/WSSettingsPane/index.js b/packages/bruno-app/src/components/RequestPane/WSSettingsPane/index.js index b1b844289..0cd7168c1 100644 --- a/packages/bruno-app/src/components/RequestPane/WSSettingsPane/index.js +++ b/packages/bruno-app/src/components/RequestPane/WSSettingsPane/index.js @@ -22,7 +22,7 @@ const getPropertyFromDraftOrRequest = (propertyKey, item) => const WSSettingsPane = ({ item, collection }) => { const dispatch = useDispatch(); - const { storedTheme, theme } = useTheme(); + const { storedTheme } = useTheme(); const { connectionTimeout, keepAliveInterval } = getPropertyFromDraftOrRequest('settings', item); diff --git a/packages/bruno-app/src/components/RequestPane/WsQueryUrl/index.js b/packages/bruno-app/src/components/RequestPane/WsQueryUrl/index.js index 11521b8ce..17531ddde 100644 --- a/packages/bruno-app/src/components/RequestPane/WsQueryUrl/index.js +++ b/packages/bruno-app/src/components/RequestPane/WsQueryUrl/index.js @@ -138,7 +138,7 @@ const WsQueryUrl = ({ item, collection, handleRun }) => { strokeWidth={1.5} size={22} /> - Close Connection + Connect )} diff --git a/packages/bruno-app/src/utils/network/index.js b/packages/bruno-app/src/utils/network/index.js index 7bee44a6b..8746f1180 100644 --- a/packages/bruno-app/src/utils/network/index.js +++ b/packages/bruno-app/src/utils/network/index.js @@ -232,18 +232,18 @@ export const sendWsRequest = (item, collection, environment, runtimeVariables) = await connectWS(item, collection, environment, runtimeVariables); } }; - ensureConnection().then(() => { - const { request } = item.draft ? item.draft : item; - sendWsMessage(item, collection.uid, request.body.ws[0].content) - .then((initialState) => { - // Return an initial state object to update the UI - // The real response data will be handled by event listeners - resolve({ - ...initialState, - }); - }) - .catch((err) => reject(err)); - }); + await ensureConnection() + const { request } = item.draft ? item.draft : item; + sendWsMessage(item, collection.uid, request.body.ws[0].content) + .then((initialState) => { + // Return an initial state object to update the UI + // The real response data will be handled by event listeners + resolve({ + ...initialState, + }); + }) + .catch((err) => reject(err)); + }); }; diff --git a/packages/bruno-electron/src/ipc/network/ws-event-handlers.js b/packages/bruno-electron/src/ipc/network/ws-event-handlers.js index df9244231..90dd7eac4 100644 --- a/packages/bruno-electron/src/ipc/network/ws-event-handlers.js +++ b/packages/bruno-electron/src/ipc/network/ws-event-handlers.js @@ -22,120 +22,29 @@ const { } = require('../../utils/oauth2'); const { interpolateString } = require('./interpolate-string'); const path = require('node:path'); - -const setWsAuthHeaders = (wsRequest, request, collectionRoot) => { - const collectionAuth = get(collectionRoot, 'request.auth'); - if (collectionAuth && request.auth?.mode === 'inherit') { - if (collectionAuth.mode === 'basic') { - wsRequest.basicAuth = { - username: get(collectionAuth, 'basic.username'), - password: get(collectionAuth, 'basic.password') - }; - } - - if (collectionAuth.mode === 'bearer') { - wsRequest.headers['Authorization'] = `Bearer ${get(collectionAuth, 'bearer.token')}`; - } - - if (collectionAuth.mode === 'apikey') { - wsRequest.headers[collectionAuth.apikey?.key] = collectionAuth.apikey?.value; - } - - if (collectionAuth.mode === 'oauth2') { - const grantType = get(collectionAuth, 'oauth2.grantType'); - - if (grantType === 'client_credentials') { - wsRequest.oauth2 = { - grantType, - accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'), - clientId: get(collectionAuth, 'oauth2.clientId'), - clientSecret: get(collectionAuth, 'oauth2.clientSecret'), - scope: get(collectionAuth, 'oauth2.scope'), - credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'), - tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'), - tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'), - tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey') - }; - } else if (grantType === 'password') { - wsRequest.oauth2 = { - grantType, - accessTokenUrl: get(collectionAuth, 'oauth2.accessTokenUrl'), - username: get(collectionAuth, 'oauth2.username'), - password: get(collectionAuth, 'oauth2.password'), - clientId: get(collectionAuth, 'oauth2.clientId'), - clientSecret: get(collectionAuth, 'oauth2.clientSecret'), - scope: get(collectionAuth, 'oauth2.scope'), - credentialsPlacement: get(collectionAuth, 'oauth2.credentialsPlacement'), - tokenPlacement: get(collectionAuth, 'oauth2.tokenPlacement'), - tokenHeaderPrefix: get(collectionAuth, 'oauth2.tokenHeaderPrefix'), - tokenQueryKey: get(collectionAuth, 'oauth2.tokenQueryKey') - }; - } - } - } - - if (request.auth && request.auth.mode !== 'inherit') { - if (request.auth.mode === 'basic') { - wsRequest.basicAuth = { - username: get(request, 'auth.basic.username'), - password: get(request, 'auth.basic.password') - }; - } - - if (request.auth.mode === 'bearer') { - wsRequest.headers['Authorization'] = `Bearer ${get(request, 'auth.bearer.token')}`; - } - - if (request.auth.mode === 'apikey') { - wsRequest.headers[get(request, 'auth.apikey.key')] = get(request, 'auth.apikey.value'); - } - - if (request.auth.mode === 'oauth2') { - const grantType = get(request, 'auth.oauth2.grantType'); - - if (grantType === 'client_credentials') { - wsRequest.oauth2 = { - grantType, - clientId: get(request, 'auth.oauth2.clientId'), - clientSecret: get(request, 'auth.oauth2.clientSecret'), - scope: get(request, 'auth.oauth2.scope'), - accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'), - tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'), - credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'), - tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'), - tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey') - }; - } else if (grantType === 'password') { - wsRequest.oauth2 = { - grantType, - username: get(request, 'auth.oauth2.username'), - password: get(request, 'auth.oauth2.password'), - clientId: get(request, 'auth.oauth2.clientId'), - clientSecret: get(request, 'auth.oauth2.clientSecret'), - scope: get(request, 'auth.oauth2.scope'), - accessTokenUrl: get(request, 'auth.oauth2.accessTokenUrl'), - tokenPlacement: get(request, 'auth.oauth2.tokenPlacement'), - credentialsPlacement: get(request, 'auth.oauth2.credentialsPlacement'), - tokenHeaderPrefix: get(request, 'auth.oauth2.tokenHeaderPrefix'), - tokenQueryKey: get(request, 'auth.oauth2.tokenQueryKey') - }; - } - } - } - - return wsRequest; -}; +const { setAuthHeaders } = require('./prepare-request'); const prepareWsRequest = async (item, collection, environment, runtimeVariables, certsAndProxyConfig = {}) => { const request = item.draft ? item.draft.request : item.request; const envVars = getEnvVars(environment); - const processEnvVars = getProcessEnvVars(); + const processEnvVars = getProcessEnvVars(collection.uid); + + const headers = {} + + each(get(request, 'headers', []), (h) => { + if (h.enabled) { + headers[h.name] = h.value; + if (h.name.toLowerCase() === 'content-type') { + contentTypeDefined = true; + } + } + }); let wsRequest = { uid: item.uid, url: request.url, - headers: request.headers || [], + headers, processEnvVars, envVars, runtimeVariables, @@ -149,7 +58,7 @@ const prepareWsRequest = async (item, collection, environment, runtimeVariables, oauth2CredentialVariables: request.oauth2CredentialVariables }; - wsRequest = setWsAuthHeaders(wsRequest, request, collection); + wsRequest = setAuthHeaders(wsRequest, request, collection); if (wsRequest.oauth2) { let requestCopy = cloneDeep(wsRequest); @@ -302,8 +211,8 @@ const registerWsEventHandlers = (window) => { }); // If the body already has messages then send it after connection - connectionInstance.on('open', () => { - const hasMessages = preparedRequest.body.ws.some(msg=>msg.content.length) + connectionInstance.on('open', async () => { + const hasMessages = preparedRequest.body.ws.some((msg) => msg.content.length); if (hasMessages) { preparedRequest.body.ws.forEach((message) => { wsClient.sendMessage(preparedRequest.uid, collection.uid, message.content); diff --git a/packages/bruno-requests/src/network/index.ts b/packages/bruno-requests/src/network/index.ts index fe254dfe3..19548a4e5 100644 --- a/packages/bruno-requests/src/network/index.ts +++ b/packages/bruno-requests/src/network/index.ts @@ -1,2 +1 @@ export { makeAxiosInstance } from './axios-instance'; -export { sendWsRequest } from './ws-request'; diff --git a/packages/bruno-requests/src/network/ws-request.ts b/packages/bruno-requests/src/network/ws-request.ts deleted file mode 100644 index 4ba1844b3..000000000 --- a/packages/bruno-requests/src/network/ws-request.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { WsClient } from '../ws/ws-client'; - -export const sendWsRequest = async (item: any, collection: any, environment: any, runtimeVariables: any) => { - // For CLI, we'll create a simple WebSocket client that connects, sends messages, and closes - // This is a simplified version for CLI usage - const request = item.draft ? item.draft : item; - const url = request.request.url; - const headers = request.request.headers || []; - const wsMessages = request.request.body?.ws || []; - - if (!url) { - throw new Error('WebSocket URL is required'); - } - - const startTime = Date.now(); - - try { - // For CLI, we'll simulate the WebSocket connection - // In a real implementation, this would use the ws library - console.log(`Connecting to WebSocket: ${url}`); - - // Simulate connection time - await new Promise((resolve) => setTimeout(resolve, 100)); - - const duration = Date.now() - startTime; - - // Return a response structure similar to HTTP responses - return { - status: 'CONNECTED', - statusCode: 0, - statusText: 'CONNECTED', - headers: headers, - body: '', - size: 0, - duration: duration, - responses: wsMessages.map((msg: any, index: number) => ({ - message: msg.content || '{}', - direction: 'sent', - timestamp: startTime + index * 100 - })), - isError: false, - error: null, - errorDetails: null, - metadata: [], - trailers: [] - }; - } catch (error) { - const duration = Date.now() - startTime; - return { - status: 'ERROR', - statusCode: 0, - statusText: 'ERROR', - headers: [], - body: '', - size: 0, - duration: duration, - responses: [], - isError: true, - error: error instanceof Error ? error.message : 'WebSocket connection failed', - errorDetails: error instanceof Error ? error.stack : null, - metadata: [], - trailers: [] - }; - } -}; diff --git a/packages/bruno-requests/src/ws/ws-client.js b/packages/bruno-requests/src/ws/ws-client.js index e8639cfd8..546fd3a7a 100644 --- a/packages/bruno-requests/src/ws/ws-client.js +++ b/packages/bruno-requests/src/ws/ws-client.js @@ -20,25 +20,6 @@ const safeJsonParse = (jsonString, context = 'JSON string') => { } }; -/** - * Process WebSocket headers into the format expected by the ws library - * @param {Array} headers - Array of header objects with name and value - * @returns {Object} Headers object for WebSocket connection - */ -const processWsHeaders = (headers) => { - const processedHeaders = {}; - - if (Array.isArray(headers)) { - headers.forEach((header) => { - if (header.name && header.value !== undefined) { - processedHeaders[header.name] = header.value; - } - }); - } - - return processedHeaders; -}; - /** * Get parsed WebSocket URL object * @param {string} url - The WebSocket URL @@ -94,11 +75,10 @@ class WsClient { * @param {Object} params.options - Additional connection options */ async startConnection({ request, collection, options = {} }) { - const { url, headers = [] } = request; + const { url, headers } = request; const { timeout = 30000, keepAlive = false, keepAliveInterval = 10_000 } = options; const parsedUrl = getParsedWsUrlObject(url); - const processedHeaders = processWsHeaders(headers); const requestId = request.uid; const collectionUid = collection.uid; @@ -106,7 +86,7 @@ class WsClient { try { // Create WebSocket connection const wsConnection = new ws.WebSocket(parsedUrl.fullUrl, { - headers: processedHeaders, + headers, timeout: timeout, followRedirects: true }); @@ -120,7 +100,7 @@ class WsClient { // Emit connecting event this.eventCallback('ws:connecting', requestId, collectionUid, { url: parsedUrl.fullUrl, - headers: processedHeaders, + headers, timestamp: Date.now() });