Implement Mihomo external-controller support in configuration and gateway
- Added optional Mihomo configuration fields in `config.compose.yaml` and `config.example.yaml` for enhanced integration with the Mihomo external-controller. - Updated the `Gateway` to handle Mihomo API requests, including proxying and error handling for Mihomo-specific endpoints. - Enhanced the documentation in `GATEWAY_RUN.md` to guide users on configuring Mihomo integration. - Introduced new utility functions in the web client for interacting with Mihomo API endpoints, improving the overall user experience. - Updated the sidebar in the Svelte components to include a link to the Mihomo section, enhancing navigation.
This commit is contained in:
@@ -7,12 +7,70 @@ import type {
|
||||
TelemtSuccess,
|
||||
UserInfo
|
||||
} from './telemt-v1.js';
|
||||
import type { MihomoMetaResponse } from './mihomo-types.js';
|
||||
|
||||
export function gatewayBase(): string {
|
||||
const u = PUBLIC_TELEMT_GATEWAY_URL || '';
|
||||
return u.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
/** Путь к Mihomo external-controller через шлюз: без ведущего слэша. */
|
||||
export function mihomoUrl(alias: string, path: string): string {
|
||||
const p = path.replace(/^\/+/, '');
|
||||
return `${gatewayBase()}/api/${encodeURIComponent(alias)}/mihomo/${p}`;
|
||||
}
|
||||
|
||||
/** WebSocket к тому же origin (ws / wss). */
|
||||
export function mihomoWsUrl(alias: string, path: string): string {
|
||||
const p = path.replace(/^\/+/, '');
|
||||
const base = gatewayBase();
|
||||
const wsBase = base.replace(/^http/, 'ws');
|
||||
return `${wsBase}/api/${encodeURIComponent(alias)}/mihomo/${p}`;
|
||||
}
|
||||
|
||||
export async function fetchMihomoMeta(alias: string): Promise<MihomoMetaResponse> {
|
||||
const res = await fetch(mihomoUrl(alias, 'meta'));
|
||||
const body = (await parseJson(res)) as Record<string, unknown> | null;
|
||||
if (res.status === 404) {
|
||||
throw new ApiError('Mihomo не настроен для этой ноды', 404, body);
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new ApiError(`Mihomo meta HTTP ${res.status}`, res.status, body);
|
||||
}
|
||||
if (!body || body.ok !== true) {
|
||||
throw new ApiError('Mihomo meta: неверный ответ', res.status, body);
|
||||
}
|
||||
return body as unknown as MihomoMetaResponse;
|
||||
}
|
||||
|
||||
export async function fetchMihomoJson<T>(alias: string, path: string): Promise<T> {
|
||||
const res = await fetch(mihomoUrl(alias, path));
|
||||
const body = await parseJson(res);
|
||||
if (res.status === 404) {
|
||||
throw new ApiError('Mihomo не настроен для этой ноды', 404, body);
|
||||
}
|
||||
if (!res.ok) {
|
||||
throw new ApiError(`Mihomo HTTP ${res.status}`, res.status, body);
|
||||
}
|
||||
return body as T;
|
||||
}
|
||||
|
||||
export async function mihomoPut(alias: string, path: string, jsonBody: unknown): Promise<void> {
|
||||
const res = await fetch(mihomoUrl(alias, path), {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(jsonBody)
|
||||
});
|
||||
if (res.status === 404) {
|
||||
const body = await parseJson(res);
|
||||
throw new ApiError('Mihomo не настроен для этой ноды', 404, body);
|
||||
}
|
||||
if (!res.ok) {
|
||||
const body = await parseJson(res);
|
||||
throw new ApiError(`Mihomo PUT HTTP ${res.status}`, res.status, body);
|
||||
}
|
||||
}
|
||||
|
||||
export type AggEnvelope<T> = {
|
||||
ok: true;
|
||||
generated_at: string;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/** GET /proxies — фрагмент ответа Mihomo external-controller. */
|
||||
export type MihomoProxiesResponse = {
|
||||
proxies?: Record<string, MihomoProxyEntry>;
|
||||
};
|
||||
|
||||
export type MihomoProxyEntry = {
|
||||
type?: string;
|
||||
name?: string;
|
||||
now?: string;
|
||||
all?: string[];
|
||||
history?: { time: string; delay: number }[];
|
||||
udp?: boolean;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type MihomoConnectionsResponse = {
|
||||
total?: number;
|
||||
connections?: MihomoConnection[];
|
||||
};
|
||||
|
||||
export type MihomoConnection = {
|
||||
metadata?: { network?: string; [k: string]: unknown };
|
||||
chains?: string[];
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type MihomoMetaResponse = {
|
||||
ok: true;
|
||||
controller_base: string;
|
||||
};
|
||||
|
||||
export type MihomoDelayResponse = {
|
||||
delay?: number;
|
||||
message?: string;
|
||||
};
|
||||
Reference in New Issue
Block a user