Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,76 @@ function App() {
export default App;
```

The only `required` parameter is `url`, which must be a `ws://` or a `wss://` (websocket) URL for the library to function properly. noVNC can display only websocket URLs. All other props to `VncScreen` are optional. The following is a list (an interface) of all props along with their types.
### Using Pre-Authenticated WebSocket

If you need to handle authentication or perform a custom handshake before establishing the VNC connection, you can pass a pre-authenticated WebSocket instance instead of a URL:

```ts
import React, { useEffect, useState } from 'react';
import { VncScreen } from 'react-vnc';

function App() {
const [websocket, setWebsocket] = useState<WebSocket | null>(null);

useEffect(() => {
// Create WebSocket and handle authentication
const ws = new WebSocket('ws://your-vnc-server.com');

ws.addEventListener('open', () => {
// Perform custom authentication or handshake
ws.send(JSON.stringify({ token: 'your-auth-token' }));
});

ws.addEventListener('message', (event) => {
const response = JSON.parse(event.data);
if (response.authenticated) {
// Once authenticated, pass the WebSocket to VncScreen
setWebsocket(ws);
}
});

return () => {
ws.close();
};
}, []);

if (!websocket) {
return <div>Authenticating...</div>;
}

return (
<VncScreen
websocket={websocket}
scaleViewport
style={{
width: '75vw',
height: '75vh',
}}
/>
);
}

export default App;
```

This approach is particularly useful for:
- Cookie-based authentication
- Custom authentication protocols
- Connection pooling or reuse
- Advanced WebSocket configuration

Either `url` or `websocket` is required:
- **`url`**: A `ws://` or `wss://` websocket URL to connect to the VNC server
- **`websocket`**: A pre-authenticated WebSocket instance (useful for custom authentication flows)

All other props to `VncScreen` are optional. The following is a list (an interface) of all props along with their types.

```ts
type EventListeners = { [T in NoVncEventType]?: (event: NoVncEvents[T]) => void };

interface Props {
url: string;
url?: string;
websocket?: WebSocket;
style?: object;
className?: string;
viewOnly?: boolean;
Expand Down
13 changes: 10 additions & 3 deletions src/lib/VncScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import RFB, { NoVncEventType, NoVncEvents, NoVncOptions } from '@novnc/novnc/lib
type EventListeners = { [T in NoVncEventType]?: (event: NoVncEvents[T]) => void };

export interface Props {
url: string;
url?: string;
websocket?: WebSocket;
style?: object;
className?: string;
viewOnly?: boolean;
Expand Down Expand Up @@ -66,6 +67,7 @@ const VncScreen: React.ForwardRefRenderFunction<VncScreenHandle, Props> = (props

const {
url,
websocket,
style,
className,
viewOnly,
Expand Down Expand Up @@ -134,7 +136,7 @@ const VncScreen: React.ForwardRefRenderFunction<VncScreenHandle, Props> = (props
}

const connected = getConnected();
if (connected) {
if (connected && !websocket) {
logger.info(`Unexpectedly disconnected from remote VNC, retrying in ${retryDuration / 1000} seconds.`);

timeouts.current.push(setTimeout(connect, retryDuration));
Expand Down Expand Up @@ -205,9 +207,14 @@ const VncScreen: React.ForwardRefRenderFunction<VncScreenHandle, Props> = (props
return;
}

if (!url && !websocket) {
logger.error('Either url or websocket must be provided');
return;
}

screen.current.innerHTML = '';

const _rfb = new RFB(screen.current, url, rfbOptions);
const _rfb = new RFB(screen.current, websocket || url!, rfbOptions);

_rfb.viewOnly = viewOnly ?? false;
_rfb.focusOnClick = focusOnClick ?? false;
Expand Down