mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-11-09 17:44:43 -06:00
Support developing in local
This commit is contained in:
3
web/.env.development
Normal file
3
web/.env.development
Normal file
@@ -0,0 +1,3 @@
|
||||
VITE_SERVER_IP=192.168.1.1
|
||||
VITE_SERVER_PORT=80
|
||||
VITE_WITH_CREDENTIALS=false
|
||||
@@ -20,31 +20,18 @@ src
|
||||
└── types // types
|
||||
```
|
||||
|
||||
## Development
|
||||
## Local Development
|
||||
|
||||
Here are some steps you can follow to develop based on your needs:
|
||||
Due to CORS restrictions, authentication needs to be disabled during local development.
|
||||
|
||||
- Log in to NanoKVM via SSH: `ssh root@your-nanokvm-ip` (default password is root);
|
||||
- Stop the current service: `killall NanoKVM-Server`.
|
||||
To develop authentication features, you need to build the project and test in NanoKVM.
|
||||
|
||||
1. Build the frontend project: `pnpm build`;
|
||||
2. Remove the files in NanoKVM: `rm -rf /kvmapp/server/web`;
|
||||
3. Upload the new files: `scp -r dist root@your-nanokvm-ip:/kvmapp/server/web`;
|
||||
4. Start the service: `/kvmapp/server/NanoKVM-Server`.
|
||||
1. Log in to NanoKVM via SSH: `ssh root@your-nanokvm-ip` (default password is root).
|
||||
2. Open the configuration file `/etc/kvm/server.yaml/` and add `authentication: disable`. ⚠️CAUTION: This option disables all authentication and should NOT be enabled in production environment!
|
||||
3. Restart the service: `/etc/init.d/S95nanokvm restart`.
|
||||
4. Edit the `.env.development` file and change `VITE_SERVER_IP` to your NanoKVM IP address.
|
||||
5. Run `pnpm dev` to start the server and visit http://localhost:3001/ in browser.
|
||||
|
||||
Then, refresh the page in the browser to see the changes.
|
||||
|
||||
### Configuration
|
||||
|
||||
**Note: Do not enable these settings in production environment unless you fully understand their purpose!**
|
||||
|
||||
In development mode, you can edit the configuration file `/etc/kvm/server.yaml` for easier development:
|
||||
|
||||
|
||||
- Add `log: debug` to print service logs. This option may cause service slowdowns, so avoid using it in production.
|
||||
- Add `authentication: disable` to disable all authentication, so don't need to log in again after restarting the service. This option should not be enabled in production!
|
||||
|
||||
### Browser
|
||||
|
||||
It's recommended to disable browser caching to avoid access issues during development:
|
||||
|
||||
|
||||
@@ -20,30 +20,18 @@ src
|
||||
└── types // 类型定义
|
||||
```
|
||||
|
||||
## 开发
|
||||
## 本地开发
|
||||
|
||||
这里给出一些参考,你可以根据自己的情况来开发。
|
||||
由于 CORS 的限制,在本地开发时,需要关闭鉴权功能。
|
||||
|
||||
- 首先通过 ssh 登录到 NanoKVM:`ssh root@your-nanokvm-ip`(默认密码为 root);
|
||||
- 停止当前服务:`killall NanoKVM-Server`。
|
||||
如果想要开发鉴权相关的功能,需要编译后在 NanoKVM 中进行测试。
|
||||
|
||||
1. 编译前端项目:`pnpm build`;
|
||||
2. 删除 NanoKVM 中前端文件:`rm -rf /kvmapp/server/web`;
|
||||
3. 重新上传前端文件:`scp -r dist root@your-nanokvm-ip:/kvmapp/server/web`;
|
||||
4. 启动服务:`/kvmapp/server/NanoKVM-Server`
|
||||
1. 通过 ssh 登录到 NanoKVM:`ssh root@your-nanokvm-ip`(默认密码为 root);
|
||||
2. 修改配置文件 `/etc/kvm/server.yaml`,添加一行 `authentication: disable`。⚠️注意:该选项会禁用所有鉴权功能,生产环境请勿开启该选项!
|
||||
3. 执行 `/etc/init.d/S95nanokvm restart` 重启服务。
|
||||
4. 编辑 `.env.development` 文件,将 `VITE_SERVER_IP` 修改为你的 NanoKVM IP 地址。
|
||||
5. 执行 `pnpm dev` 启动服务,然后在浏览器中访问 http://localhost:3001/ 。
|
||||
|
||||
最后,在浏览器中刷新页面即可。
|
||||
|
||||
### 配置文件
|
||||
|
||||
**注意:请勿在生产环境中开启这些配置项!除非你了解每个配置的用途。**
|
||||
|
||||
在开发模式下,为了更方便的开发,可以修改配置文件 `/etc/kvm/server.yaml`。
|
||||
|
||||
- 添加 `log: debug`,会打印服务日志。该选项可能导致服务卡顿,生产环境中请勿开启。
|
||||
- 添加 `authentication: disable`,会禁用所有鉴权,服务重启后也不再需要重新登录。生产环境请勿开启该选项!
|
||||
|
||||
### 浏览器设置
|
||||
|
||||
建议在浏览器中禁用缓存,防止在开发过程中出现无法访问的情况。
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { removeToken } from '@/lib/cookie.ts';
|
||||
import { getBaseUrl } from '@/lib/service.ts';
|
||||
|
||||
type Response = {
|
||||
code: number;
|
||||
@@ -12,9 +13,12 @@ class Http {
|
||||
private instance: AxiosInstance;
|
||||
|
||||
constructor() {
|
||||
const baseURL = getBaseUrl('http');
|
||||
const withCredentials = (import.meta.env.VITE_WITH_CREDENTIALS as string) !== 'false';
|
||||
|
||||
this.instance = axios.create({
|
||||
baseURL: this.getBaseURL(),
|
||||
withCredentials: true,
|
||||
baseURL,
|
||||
withCredentials,
|
||||
timeout: 60 * 1000
|
||||
});
|
||||
|
||||
@@ -46,10 +50,6 @@ class Http {
|
||||
);
|
||||
}
|
||||
|
||||
public getBaseURL() {
|
||||
return `${window.location.protocol}//${window.location.host}`;
|
||||
}
|
||||
|
||||
public get(url: string, params?: any): Promise<Response> {
|
||||
return this.instance.request({
|
||||
method: 'get',
|
||||
|
||||
21
web/src/lib/service.ts
Normal file
21
web/src/lib/service.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export function getHostname(): string {
|
||||
const ip = import.meta.env.VITE_SERVER_IP as string;
|
||||
return ip ? ip : window.location.hostname;
|
||||
}
|
||||
|
||||
export function getPort(): string {
|
||||
const port = import.meta.env.VITE_SERVER_PORT as string;
|
||||
return port ? port : window.location.port;
|
||||
}
|
||||
|
||||
export function getBaseUrl(type: 'http' | 'ws'): string {
|
||||
let protocol = window.location.protocol;
|
||||
if (type === 'ws') {
|
||||
protocol = protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
}
|
||||
|
||||
const hostname = getHostname();
|
||||
const port = getPort();
|
||||
|
||||
return `${protocol}//${hostname}:${port}`;
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
import { w3cwebsocket as W3cWebSocket } from 'websocket';
|
||||
|
||||
import { getBaseUrl } from '@/lib/service.ts';
|
||||
|
||||
class WsClient {
|
||||
private readonly url: string;
|
||||
private instance: W3cWebSocket;
|
||||
|
||||
constructor() {
|
||||
const url = this.getUrl();
|
||||
this.instance = new W3cWebSocket(url);
|
||||
}
|
||||
|
||||
private getUrl() {
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
return `${protocol}//${window.location.host}/api/ws`;
|
||||
this.url = `${getBaseUrl('ws')}/api/ws`;
|
||||
this.instance = new W3cWebSocket(this.url);
|
||||
}
|
||||
|
||||
public connect() {
|
||||
this.close();
|
||||
|
||||
const url = this.getUrl();
|
||||
this.instance = new W3cWebSocket(url);
|
||||
this.instance = new W3cWebSocket(this.url);
|
||||
}
|
||||
|
||||
public send(data: number[]) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useAtomValue } from 'jotai';
|
||||
|
||||
import MonitorXIcon from '@/assets/images/monitor-x.svg';
|
||||
import { stopFrameDetect } from '@/api/stream.ts';
|
||||
import { getBaseUrl } from '@/lib/service.ts';
|
||||
import { mouseStyleAtom } from '@/jotai/mouse.ts';
|
||||
import { resolutionAtom } from '@/jotai/resolution.ts';
|
||||
|
||||
@@ -31,7 +32,7 @@ export const Screen = () => {
|
||||
)}
|
||||
width={resolution!.width}
|
||||
height={resolution!.height}
|
||||
src={`${window.location.protocol}//${window.location.host}/api/stream/mjpeg`}
|
||||
src={`${getBaseUrl('http')}/api/stream/mjpeg`}
|
||||
fallback={MonitorXIcon}
|
||||
preview={false}
|
||||
/>
|
||||
|
||||
@@ -5,6 +5,8 @@ import { Terminal as XtermTerminal } from '@xterm/xterm';
|
||||
|
||||
import '@xterm/xterm/css/xterm.css';
|
||||
|
||||
import { getBaseUrl } from '@/lib/service.ts';
|
||||
|
||||
type TerminalProps = {
|
||||
token: string;
|
||||
setToken: (token: string) => void;
|
||||
@@ -21,8 +23,7 @@ export const Xterm = ({ token, setToken }: TerminalProps) => {
|
||||
terminal.open(terminalEle);
|
||||
fitAddon.fit();
|
||||
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = `${protocol}//${window.location.host}/api/vm/terminal?${token}`;
|
||||
const url = `${getBaseUrl('ws')}/api/vm/terminal?${token}`;
|
||||
const webSocket = new WebSocket(url);
|
||||
|
||||
const sendSize = () => {
|
||||
|
||||
Reference in New Issue
Block a user