summaryrefslogtreecommitdiff
path: root/src/api
diff options
context:
space:
mode:
authorHaishan <[email protected]>2020-09-05 00:02:53 +0800
committerHaishan <[email protected]>2020-09-08 23:15:04 +0800
commit702169941e6956aa8f3b727ffe59a7bd6676c346 (patch)
treecbac8bb16592229b0499ab43a646df3bc67e0a2c /src/api
parent64ea28607a2077ac503cdb507d80632ba56e22f6 (diff)
refactor: use api base url instead of hostname and port
Diffstat (limited to 'src/api')
-rw-r--r--src/api/configs.js30
-rw-r--r--src/api/configs.ts31
-rw-r--r--src/api/connections.ts (renamed from src/api/connections.js)76
-rw-r--r--src/api/logs.ts (renamed from src/api/logs.js)58
-rw-r--r--src/api/traffic.js13
5 files changed, 93 insertions, 115 deletions
diff --git a/src/api/configs.js b/src/api/configs.js
deleted file mode 100644
index 42f8ff0..0000000
--- a/src/api/configs.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { getURLAndInit } from '../misc/request-helper';
-
-const endpoint = '/configs';
-
-export async function fetchConfigs(apiConfig) {
- const { url, init } = getURLAndInit(apiConfig);
- return await fetch(url + endpoint, init);
-}
-
-// TODO support PUT /configs
-// req body
-// { Path: string }
-
-function configsPatchWorkaround(o) {
- // backward compatibility for older clash using `socket-port`
- if ('socks-port' in o) {
- o['socket-port'] = o['socks-port'];
- }
- return o;
-}
-
-export async function updateConfigs(apiConfig, o) {
- const { url, init } = getURLAndInit(apiConfig);
- return await fetch(url + endpoint, {
- ...init,
- method: 'PATCH',
- // mode: 'cors',
- body: JSON.stringify(configsPatchWorkaround(o))
- });
-}
diff --git a/src/api/configs.ts b/src/api/configs.ts
new file mode 100644
index 0000000..4957e85
--- /dev/null
+++ b/src/api/configs.ts
@@ -0,0 +1,31 @@
+import { getURLAndInit } from 'src/misc/request-helper';
+import { ClashAPIConfig } from 'src/types';
+
+const endpoint = '/configs';
+
+export async function fetchConfigs(apiConfig: ClashAPIConfig) {
+ const { url, init } = getURLAndInit(apiConfig);
+ return await fetch(url + endpoint, init);
+}
+
+// TODO support PUT /configs
+// req body
+// { Path: string }
+
+type ClashConfigPartial = { 'socks-port'?: unknown };
+function configsPatchWorkaround(o: ClashConfigPartial) {
+ // backward compatibility for older clash using `socket-port`
+ if ('socks-port' in o) {
+ o['socket-port'] = o['socks-port'];
+ }
+ return o;
+}
+
+export async function updateConfigs(
+ apiConfig: ClashAPIConfig,
+ o: ClashConfigPartial
+) {
+ const { url, init } = getURLAndInit(apiConfig);
+ const body = JSON.stringify(configsPatchWorkaround(o));
+ return await fetch(url + endpoint, { ...init, body, method: 'PATCH' });
+}
diff --git a/src/api/connections.js b/src/api/connections.ts
index f540c74..7608a41 100644
--- a/src/api/connections.js
+++ b/src/api/connections.ts
@@ -1,4 +1,6 @@
-import { getURLAndInit } from '../misc/request-helper';
+import { ClashAPIConfig } from 'src/types';
+
+import { buildWebSocketURL, getURLAndInit } from '../misc/request-helper';
const endpoint = '/connections';
@@ -8,31 +10,31 @@ const subscribers = [];
// see also https://github.com/Dreamacro/clash/blob/dev/constant/metadata.go#L41
type UUID = string;
type ConnectionItem = {
- id: UUID,
+ id: UUID;
metadata: {
- network: 'tcp' | 'udp',
- type: 'HTTP' | 'HTTP Connect' | 'Socks5' | 'Redir' | 'Unknown',
- sourceIP: string,
- destinationIP: string,
- sourcePort: string,
- destinationPort: string,
- host: string,
- },
- upload: number,
- download: number,
+ network: 'tcp' | 'udp';
+ type: 'HTTP' | 'HTTP Connect' | 'Socks5' | 'Redir' | 'Unknown';
+ sourceIP: string;
+ destinationIP: string;
+ sourcePort: string;
+ destinationPort: string;
+ host: string;
+ };
+ upload: number;
+ download: number;
// e.g. "2019-11-30T22:48:13.416668+08:00",
- start: string,
- chains: Array<string>,
+ start: string;
+ chains: Array<string>;
// e.g. 'Match', 'DomainKeyword'
- rule: string,
+ rule: string;
};
type ConnectionsData = {
- downloadTotal: number,
- uploadTotal: number,
- connections: Array<ConnectionItem>,
+ downloadTotal: number;
+ uploadTotal: number;
+ connections: Array<ConnectionItem>;
};
-function appendData(s) {
+function appendData(s: string) {
let o: ConnectionsData;
try {
o = JSON.parse(s);
@@ -43,33 +45,25 @@ function appendData(s) {
subscribers.forEach((f) => f(o));
}
-function getWsUrl(apiConfig) {
- const { hostname, port, secret } = apiConfig;
- let qs = '';
- if (typeof secret === 'string' && secret !== '') {
- qs += '?token=' + encodeURIComponent(secret);
- }
- return `ws://${hostname}:${port}${endpoint}${qs}`;
-}
+type UnsubscribeFn = () => void;
-let wsState;
-function fetchData(apiConfig, listener) {
+let wsState: number;
+export function fetchData(
+ apiConfig: ClashAPIConfig,
+ listener: unknown
+): UnsubscribeFn | void {
if (fetched || wsState === 1) {
if (listener) return subscribe(listener);
}
wsState = 1;
- const url = getWsUrl(apiConfig);
+ const url = buildWebSocketURL(apiConfig, endpoint);
const ws = new WebSocket(url);
- ws.addEventListener('error', function (_ev) {
- wsState = 3;
- });
- ws.addEventListener('message', function (event) {
- appendData(event.data);
- });
+ ws.addEventListener('error', () => (wsState = 3));
+ ws.addEventListener('message', (event) => appendData(event.data));
if (listener) return subscribe(listener);
}
-function subscribe(listener) {
+function subscribe(listener: unknown): UnsubscribeFn {
subscribers.push(listener);
return function unsubscribe() {
const idx = subscribers.indexOf(listener);
@@ -77,20 +71,18 @@ function subscribe(listener) {
};
}
-async function closeAllConnections(apiConfig) {
+export async function closeAllConnections(apiConfig: ClashAPIConfig) {
const { url, init } = getURLAndInit(apiConfig);
return await fetch(url + endpoint, { ...init, method: 'DELETE' });
}
-export async function fetchConns(apiConfig) {
+export async function fetchConns(apiConfig: ClashAPIConfig) {
const { url, init } = getURLAndInit(apiConfig);
return await fetch(url + endpoint, { ...init });
}
-export async function closeConnById(apiConfig, id) {
+export async function closeConnById(apiConfig: ClashAPIConfig, id: string) {
const { url: baseURL, init } = getURLAndInit(apiConfig);
const url = `${baseURL}${endpoint}/${id}`;
return await fetch(url, { ...init, method: 'DELETE' });
}
-
-export { fetchData, closeAllConnections };
diff --git a/src/api/logs.js b/src/api/logs.ts
index caabd04..1958638 100644
--- a/src/api/logs.js
+++ b/src/api/logs.ts
@@ -1,4 +1,16 @@
-import { getURLAndInit } from '../misc/request-helper';
+import { ClashAPIConfig } from 'src/types';
+
+import { buildWebSocketURL, getURLAndInit } from '../misc/request-helper';
+
+type LogsAPIConfig = ClashAPIConfig & { logLevel: string };
+type LogEntry = {
+ time?: string;
+ id?: string;
+ even?: boolean;
+ // and some other props
+};
+type AppendLogFn = (x: LogEntry) => void;
+
const endpoint = '/logs';
const textDecoder = new TextDecoder('utf-8');
@@ -10,8 +22,8 @@ let even = false;
let fetched = false;
let decoded = '';
-function appendData(s, callback) {
- let o;
+function appendData(s: string, callback: AppendLogFn) {
+ let o: LogEntry;
try {
o = JSON.parse(s);
} catch (err) {
@@ -23,12 +35,12 @@ function appendData(s, callback) {
const time = now.toLocaleString('zh-Hans');
// mutate input param in place intentionally
o.time = time;
- o.id = now - 0 + getRandomStr();
+ o.id = +now - 0 + getRandomStr();
o.even = even = !even;
callback(o);
}
-function pump(reader, appendLog) {
+function pump(reader: ReadableStreamDefaultReader, appendLog: AppendLogFn) {
return reader.read().then(({ done, value }) => {
const str = textDecoder.decode(value, { stream: !done });
decoded += str;
@@ -56,31 +68,20 @@ function pump(reader, appendLog) {
});
}
-const apiConfigSnapshot = {};
-let controller;
-
-function getWsUrl(apiConfig) {
- const { hostname, port, secret, logLevel } = apiConfig;
- let qs = '?level=' + logLevel;
- if (typeof secret === 'string' && secret !== '') {
- qs += '&token=' + encodeURIComponent(secret);
- }
- return `ws://${hostname}:${port}${endpoint}${qs}`;
-}
+let apiConfigSnapshot: LogsAPIConfig;
+let controller: AbortController;
// 1 OPEN
// other value CLOSED
// similar to ws readyState but not the same
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
-let wsState;
-function fetchLogs(apiConfig, appendLog) {
+let wsState: number;
+export function fetchLogs(apiConfig: LogsAPIConfig, appendLog: AppendLogFn) {
if (fetched || wsState === 1) return;
wsState = 1;
- const url = getWsUrl(apiConfig);
+ const url = buildWebSocketURL(apiConfig, endpoint);
const ws = new WebSocket(url);
- ws.addEventListener('error', function (_ev) {
- wsState = 3;
- });
+ ws.addEventListener('error', () => (wsState = 3));
ws.addEventListener('close', function (_ev) {
wsState = 3;
fetchLogsWithFetch(apiConfig, appendLog);
@@ -90,11 +91,10 @@ function fetchLogs(apiConfig, appendLog) {
});
}
-function fetchLogsWithFetch(apiConfig, appendLog) {
+function fetchLogsWithFetch(apiConfig: LogsAPIConfig, appendLog: AppendLogFn) {
if (
controller &&
- (apiConfigSnapshot.hostname !== apiConfig.hostname ||
- apiConfigSnapshot.port !== apiConfig.port ||
+ (apiConfigSnapshot.baseURL !== apiConfig.baseURL ||
apiConfigSnapshot.secret !== apiConfig.secret ||
apiConfigSnapshot.logLevel !== apiConfig.logLevel)
) {
@@ -104,11 +104,7 @@ function fetchLogsWithFetch(apiConfig, appendLog) {
}
fetched = true;
-
- apiConfigSnapshot.hostname = apiConfig.hostname;
- apiConfigSnapshot.port = apiConfig.port;
- apiConfigSnapshot.secret = apiConfig.secret;
- apiConfigSnapshot.logLevel = apiConfig.logLevel;
+ apiConfigSnapshot = { ...apiConfig };
controller = new AbortController();
const signal = controller.signal;
@@ -131,5 +127,3 @@ function fetchLogsWithFetch(apiConfig, appendLog) {
}
);
}
-
-export { fetchLogs };
diff --git a/src/api/traffic.js b/src/api/traffic.js
index f3f33ca..e50ec5e 100644
--- a/src/api/traffic.js
+++ b/src/api/traffic.js
@@ -1,4 +1,4 @@
-import { getURLAndInit } from '../misc/request-helper';
+import { buildWebSocketURL, getURLAndInit } from '../misc/request-helper';
const endpoint = '/traffic';
const textDecoder = new TextDecoder('utf-8');
@@ -69,15 +69,6 @@ function pump(reader) {
});
}
-function getWsUrl(apiConfig) {
- const { hostname, port, secret } = apiConfig;
- let qs = '';
- if (typeof secret === 'string' && secret !== '') {
- qs += '?token=' + encodeURIComponent(secret);
- }
- return `ws://${hostname}:${port}${endpoint}${qs}`;
-}
-
// 1 OPEN
// other value CLOSED
// similar to ws readyState but not the same
@@ -86,7 +77,7 @@ let wsState;
function fetchData(apiConfig) {
if (fetched || wsState === 1) return traffic;
wsState = 1;
- const url = getWsUrl(apiConfig);
+ const url = buildWebSocketURL(apiConfig, endpoint);
const ws = new WebSocket(url);
ws.addEventListener('error', function (_ev) {
wsState = 3;