diff --git a/src/k8s/__tests__/k8s-utils.spec.ts b/src/k8s/__tests__/k8s-utils.spec.ts new file mode 100644 index 0000000..3d02fc3 --- /dev/null +++ b/src/k8s/__tests__/k8s-utils.spec.ts @@ -0,0 +1,47 @@ +import { getWebsocketSubProtocolAndPathPrefix } from '../k8s-utils'; + +describe('getWebsocketSubProtocolAndPathPrefix', () => { + it('should return correct path with leading slash, host, and subProtocols', () => { + const path = '/example-path'; + const result = getWebsocketSubProtocolAndPathPrefix(path); + + expect(result).toEqual({ + path: '/wss/k8s/example-path', + host: 'auto', + subProtocols: ['base64.binary.k8s.io'], + }); + }); + + it('should set path to undefined if an empty string is provided', () => { + const path = ''; + const result = getWebsocketSubProtocolAndPathPrefix(path); + + expect(result).toEqual({ + path: undefined, + host: 'auto', + subProtocols: ['base64.binary.k8s.io'], + }); + }); + + it('should add a leading slash to paths without one', () => { + const path = 'no-leading-slash'; + const result = getWebsocketSubProtocolAndPathPrefix(path); + + expect(result).toEqual({ + path: '/wss/k8s/no-leading-slash', + host: 'auto', + subProtocols: ['base64.binary.k8s.io'], + }); + }); + + it('should not add an extra leading slash if the path already has one', () => { + const path = '/already-has-slash'; + const result = getWebsocketSubProtocolAndPathPrefix(path); + + expect(result).toEqual({ + path: '/wss/k8s/already-has-slash', + host: 'auto', + subProtocols: ['base64.binary.k8s.io'], + }); + }); +}); diff --git a/src/k8s/k8s-utils.ts b/src/k8s/k8s-utils.ts index 35c2c61..f86b0c3 100644 --- a/src/k8s/k8s-utils.ts +++ b/src/k8s/k8s-utils.ts @@ -188,6 +188,18 @@ export const getK8sResourceURL = ( return resourcePath; }; +/** + * returns websocket subprotocol, host with added prefix to path + * @param path {String} + */ +export const getWebsocketSubProtocolAndPathPrefix = (path: string) => { + return { + path: path === '' ? undefined : `/wss/k8s${path.startsWith('/') ? path : `/${path}`}`, + host: 'auto', + subProtocols: ['base64.binary.k8s.io'], + }; +}; + export const k8sWatch = ( kind: K8sModelCommon, query: { @@ -239,11 +251,11 @@ export const k8sWatch = ( } const path = getK8sResourceURL(kind, undefined, opts); - wsOptionsUpdated.path = `/wss/k8s${path}`; - wsOptionsUpdated.host = 'auto'; - wsOptionsUpdated.subProtocols = ['base64.binary.k8s.io']; - return new WebSocketFactory(path, wsOptionsUpdated); + return new WebSocketFactory(path, { + ...wsOptionsUpdated, + ...getWebsocketSubProtocolAndPathPrefix(path), + }); }; /** diff --git a/src/shared/components/pipeline-run-logs/logs/Logs.tsx b/src/shared/components/pipeline-run-logs/logs/Logs.tsx index 5b72eae..b46799f 100644 --- a/src/shared/components/pipeline-run-logs/logs/Logs.tsx +++ b/src/shared/components/pipeline-run-logs/logs/Logs.tsx @@ -4,7 +4,7 @@ import { Alert } from '@patternfly/react-core'; import { Base64 } from 'js-base64'; import { useWorkspaceInfo } from '../../../../components/Workspace/useWorkspaceInfo'; import { commonFetchText } from '../../../../k8s'; -import { getK8sResourceURL } from '../../../../k8s/k8s-utils'; +import { getK8sResourceURL, getWebsocketSubProtocolAndPathPrefix } from '../../../../k8s/k8s-utils'; import { WebSocketFactory } from '../../../../k8s/web-socket/WebSocketFactory'; import { PodModel } from '../../../../models/pod'; import { ContainerSpec, PodKind } from '../../types'; @@ -107,9 +107,7 @@ const Logs: React.FC> = ({ onCompleteRef.current(name); }); } else { - const wsOpts = { - path: watchURL, - }; + const wsOpts = getWebsocketSubProtocolAndPathPrefix(watchURL); ws = new WebSocketFactory(watchURL, wsOpts); ws.onMessage((msg) => { if (loaded) return; diff --git a/src/shared/components/pipeline-run-logs/logs/LogsWrapperComponent.tsx b/src/shared/components/pipeline-run-logs/logs/LogsWrapperComponent.tsx index 27c01fa..7c662e5 100644 --- a/src/shared/components/pipeline-run-logs/logs/LogsWrapperComponent.tsx +++ b/src/shared/components/pipeline-run-logs/logs/LogsWrapperComponent.tsx @@ -32,7 +32,7 @@ const LogsWrapperComponent: React.FC(resource, PodModel, { retry: false }); + } = useK8sWatchResource({ ...resource, watch: true }, PodModel, { retry: false }); const [isFullscreen, fullscreenRef, fullscreenToggle] = useFullscreen(); const [downloadAllStatus, setDownloadAllStatus] = React.useState(false); const currentLogGetterRef = React.useRef<() => string>();