fix: fix header movement and minor cleanup

This commit is contained in:
Siddharth Gelera
2025-09-15 18:56:44 +05:30
parent 5955a15d18
commit 1bf47039d1
7 changed files with 34 additions and 211 deletions

View File

@@ -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);

View File

@@ -138,7 +138,7 @@ const WsQueryUrl = ({ item, collection, handleRun }) => {
strokeWidth={1.5}
size={22}
/>
<span className="infotip-text text-xs">Close Connection</span>
<span className="infotip-text text-xs">Connect</span>
</div>
</div>
)}

View File

@@ -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));
});
};

View File

@@ -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);

View File

@@ -1,2 +1 @@
export { makeAxiosInstance } from './axios-instance';
export { sendWsRequest } from './ws-request';

View File

@@ -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: []
};
}
};

View File

@@ -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()
});