mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-26 14:15:52 +00:00
feat: better subprotocol support and tests
This commit is contained in:
@@ -88,11 +88,20 @@ class WsClient {
|
||||
|
||||
try {
|
||||
// Create WebSocket connection
|
||||
const wsConnection = new ws.WebSocket(parsedUrl.fullUrl, {
|
||||
const protocols = [].concat([headers['Sec-WebSocket-Protocol'], headers['sec-websocket-protocol']]).filter(Boolean);
|
||||
const protocolVersion = headers['Sec-WebSocket-Version'] || headers['sec-websocket-version'];
|
||||
|
||||
const wsOptions = {
|
||||
headers,
|
||||
handshakeTimeout: timeout,
|
||||
followRedirects: true,
|
||||
});
|
||||
};
|
||||
|
||||
if (protocolVersion) {
|
||||
wsOptions.protocolVersion = protocolVersion;
|
||||
}
|
||||
|
||||
const wsConnection = new ws.WebSocket(parsedUrl.fullUrl, protocols, wsOptions);
|
||||
|
||||
// Set up event handlers
|
||||
this.#setupWsEventHandlers(wsConnection, requestId, collectionUid, { keepAlive, keepAliveInterval });
|
||||
|
||||
@@ -5,7 +5,16 @@ const onSocketError = (err) => {
|
||||
};
|
||||
|
||||
const wss = new ws.Server({
|
||||
noServer: true
|
||||
noServer: true,
|
||||
handleProtocols: (protocols, request) => {
|
||||
if (request.url == '/ws/sub-proto') {
|
||||
if (protocols.has("soap")) {
|
||||
return 'soap'
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
});
|
||||
|
||||
wss.on('connection', function connection(ws, request) {
|
||||
@@ -31,7 +40,7 @@ wss.on('connection', function connection(ws, request) {
|
||||
const wsRouter = (request, socket, head) => {
|
||||
socket.on('error', onSocketError);
|
||||
|
||||
if (request.url !== '/ws') {
|
||||
if (!request.url.startsWith('/ws')) {
|
||||
socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
|
||||
socket.destroy();
|
||||
|
||||
@@ -39,6 +48,24 @@ const wsRouter = (request, socket, head) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.url == '/ws/sub-proto') {
|
||||
const subproto = request.headers["sec-websocket-protocol"] || request.headers["Sec-WebSocket-Protocol"]
|
||||
if (subproto != "soap") {
|
||||
const message = "Unsupported WebSocket subprotocol"
|
||||
socket.write(
|
||||
'HTTP/1.1 400 Bad Request\r\n' +
|
||||
'Content-Type: text/plain\r\n' +
|
||||
`Content-Length: ${Buffer.byteLength(message)}\r\n` +
|
||||
'Connection: close\r\n' +
|
||||
'\r\n' +
|
||||
message
|
||||
);
|
||||
socket.destroy();
|
||||
socket.removeListener('error', onSocketError);
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
wss.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wss.emit('connection', ws, request);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
meta {
|
||||
name: ws-test-request-with-subproto
|
||||
type: ws
|
||||
seq: 3
|
||||
}
|
||||
|
||||
ws {
|
||||
url: ws://localhost:8081/ws/sub-proto
|
||||
body: ws
|
||||
auth: inherit
|
||||
}
|
||||
|
||||
headers {
|
||||
Sec-WebSocket-Protocol: soap
|
||||
}
|
||||
|
||||
body:ws {
|
||||
name: message 1
|
||||
content: '''
|
||||
{}
|
||||
'''
|
||||
}
|
||||
41
tests/websockets/subproto.spec.ts
Normal file
41
tests/websockets/subproto.spec.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { test, expect } from '../../playwright';
|
||||
import { buildCommonLocators } from './lib/locators';
|
||||
|
||||
const BRU_FILE_NAME = /^ws-test-request-with-subproto$/;
|
||||
|
||||
test.describe.serial('headers', () => {
|
||||
test('headers are returned if passed', async ({ pageWithUserData: page, restartApp }) => {
|
||||
const locators = buildCommonLocators(page);
|
||||
const clearText = async (text: string) => {
|
||||
for (let i = text.length; i > 0; i--) {
|
||||
await page.keyboard.press('Backspace');
|
||||
}
|
||||
};
|
||||
const originalProtocol = 'soap';
|
||||
const wrongProtocol = 'wap';
|
||||
|
||||
await page.locator('#sidebar-collection-name').click();
|
||||
await page.getByTitle(BRU_FILE_NAME).click();
|
||||
await page.getByRole('tab', { name: 'Headers1' }).click();
|
||||
|
||||
await expect(page.locator('pre').filter({ hasText: originalProtocol })).toBeAttached();
|
||||
await locators.runner().click();
|
||||
|
||||
const messages = await locators.messages();
|
||||
expect(await messages[0].locator('.text-ellipsis').innerText()).toMatch(/^(Connected to)/);
|
||||
|
||||
await locators.connectionControls.disconnect().click();
|
||||
|
||||
await page.locator('pre').filter({ hasText: originalProtocol }).click();
|
||||
await clearText(originalProtocol);
|
||||
await page.keyboard.insertText(wrongProtocol);
|
||||
|
||||
await locators.runner().click();
|
||||
expect(await messages[0].locator('.text-ellipsis').innerText()).toMatch(/^(Unexpected server response: 400)/);
|
||||
|
||||
await page.locator('pre').filter({ hasText: wrongProtocol }).click();
|
||||
await clearText(wrongProtocol);
|
||||
await page.keyboard.insertText(originalProtocol);
|
||||
await locators.saveButton().click();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user