diff --git a/package.json b/package.json
index 32109138..99f759a0 100644
--- a/package.json
+++ b/package.json
@@ -69,7 +69,6 @@
"mnemonist": "^0.40.3",
"mobile-drag-drop": "3.0.0-rc.0",
"msgpackr": "1.10.1",
- "node-fetch": "2",
"node-html-parser": "^6.1.12",
"ollama": "^0.5.0",
"pdfjs-dist": "^4.0.379",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c460c2c9..f247c718 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -158,15 +158,15 @@ importers:
ml-distance:
specifier: ^4.0.1
version: 4.0.1
+ mnemonist:
+ specifier: ^0.40.3
+ version: 0.40.3
mobile-drag-drop:
specifier: 3.0.0-rc.0
version: 3.0.0-rc.0
msgpackr:
specifier: 1.10.1
version: 1.10.1
- node-fetch:
- specifier: '2'
- version: 2.7.0
node-html-parser:
specifier: ^6.1.12
version: 6.1.12
@@ -2756,6 +2756,9 @@ packages:
ml-tree-similarity@1.0.0:
resolution: {integrity: sha512-XJUyYqjSuUQkNQHMscr6tcjldsOoAekxADTplt40QKfwW6nd++1wHWV9AArl0Zvw/TIHgNaZZNvr8QGvE8wLRg==}
+ mnemonist@0.40.3:
+ resolution: {integrity: sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==}
+
mobile-drag-drop@3.0.0-rc.0:
resolution: {integrity: sha512-f8wIDTbBYLBW/+5sei1cqUE+StyDpf/LP+FRZELlVX6tmOOmELk84r3wh1z3woxCB9G5octhF06K5COvFjGgqg==}
@@ -2900,6 +2903,9 @@ packages:
object-inspect@1.13.1:
resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==}
+ obliterator@2.0.5:
+ resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==}
+
ollama@0.5.0:
resolution: {integrity: sha512-CRtRzsho210EGdK52GrUMohA2pU+7NbgEaBG3DcYeRmvQthDO7E2LHOkLlUUeaYUlNmEd8icbjC02ug9meSYnw==}
@@ -6505,6 +6511,10 @@ snapshots:
binary-search: 1.3.6
num-sort: 2.1.0
+ mnemonist@0.40.3:
+ dependencies:
+ obliterator: 2.0.5
+
mobile-drag-drop@3.0.0-rc.0: {}
modify-values@1.0.1: {}
@@ -6665,6 +6675,8 @@ snapshots:
object-inspect@1.13.1: {}
+ obliterator@2.0.5: {}
+
ollama@0.5.0:
dependencies:
whatwg-fetch: 3.6.20
diff --git a/server/node/server.cjs b/server/node/server.cjs
index b2871d9d..0828d9f7 100644
--- a/server/node/server.cjs
+++ b/server/node/server.cjs
@@ -11,8 +11,7 @@ app.use(express.raw({ type: 'application/octet-stream', limit: '50mb' }));
const {pipeline} = require('stream/promises')
const https = require('https');
const sslPath = path.join(process.cwd(), 'server/node/ssl/certificate');
-const EXTERNAL_HUB_URL = 'https://sv.risuai.xyz';
-const fetch = require('node-fetch');
+const hubURL = 'https://sv.risuai.xyz';
let password = ''
@@ -31,12 +30,17 @@ function isHex(str) {
}
app.get('/', async (req, res, next) => {
- console.log("[Server] Connected")
+
+ const clientIP = req.headers['x-forwarded-for'] || req.ip || req.socket.remoteAddress || 'Unknown IP';
+ const timestamp = new Date().toISOString();
+ console.log(`[Server] ${timestamp} | Connection from: ${clientIP}`);
+
try {
const mainIndex = await fs.readFile(path.join(process.cwd(), 'dist', 'index.html'))
const root = htmlparser.parse(mainIndex)
const head = root.querySelector('head')
head.innerHTML = `` + head.innerHTML
+
res.send(root.toString())
} catch (error) {
console.log(error)
@@ -139,116 +143,69 @@ const reverseProxyFunc_get = async (req, res, next) => {
}
}
-// Risu Realm Proxy
-async function hubProxyHandler(req, res, next) {
+async function hubProxyFunc(req, res) {
+
try {
- // Extract request path and query parameters
const pathAndQuery = req.originalUrl.replace(/^\/hub-proxy/, '');
- const externalURL = EXTERNAL_HUB_URL + pathAndQuery;
-
- console.log(`[Hub Proxy] Forwarding ${req.method} request to: ${externalURL}`);
-
- // Prepare headers to send to the realm server (including Accept-Encoding modification)
+ const externalURL = hubURL + pathAndQuery;
+
const headersToSend = { ...req.headers };
- delete headersToSend['host'];
- delete headersToSend['connection'];
- headersToSend['accept-encoding'] = 'gzip, deflate'; // Exclude zstd, etc.
- if (!headersToSend['x-forwarded-for']) {
- headersToSend['x-forwarded-for'] = req.ip;
- }
-
- // Execute the fetch request to the realm server
+ delete headersToSend.host;
+ delete headersToSend.connection;
+
const response = await fetch(externalURL, {
method: req.method,
headers: headersToSend,
- body: (req.method !== 'GET' && req.method !== 'HEAD') ? req.body : undefined,
+ body: req.method !== 'GET' && req.method !== 'HEAD' ? req : undefined,
+ redirect: 'manual',
+ duplex: 'half'
});
-
- console.log(`[Hub Proxy] Received status ${response.status} from external server`);
-
- // Handle the realm server response
- // Clean up response headers and extract Content-Type
- const responseHeaders = {};
- // Check the Content-Type of the realm server response (use default if missing)
- let contentType = response.headers.get('content-type') || 'application/octet-stream';
-
- response.headers.forEach((value, key) => {
- const lowerKey = key.toLowerCase();
- // List of headers not to be forwarded to the client
- const excludedHeaders = [
- 'transfer-encoding', 'connection', 'content-encoding',
- 'access-control-allow-origin', 'access-control-allow-methods',
- 'access-control-allow-headers', 'content-security-policy',
- 'content-security-policy-report-only', 'clear-site-data',
- 'strict-transport-security', 'expect-ct',
- 'cf-ray', 'cf-cache-status', 'report-to', 'nel', 'server', 'server-timing', 'alt-svc'
- ];
- if (!excludedHeaders.includes(lowerKey)) {
- responseHeaders[key] = value;
- }
- });
-
- // Set the status code and cleaned headers for the client
- res.status(response.status).set(responseHeaders);
-
- // Determine body processing method based on Content-Type
- try {
- if (contentType.startsWith('application/json')) {
- // JSON response: read as text and send
- const bodyText = await response.text();
- console.log(`[Hub Proxy] Processing JSON response (size: ${bodyText.length})`);
- res.setHeader('Content-Type', contentType); // Set the final Content-Type
- res.send(bodyText);
-
- } else if (contentType.startsWith('image/')) {
- // Image response: read as buffer and send
- const bodyBuffer = await response.buffer(); // Assuming 'fetch' response object has a .buffer() method or similar
- console.log(`[Hub Proxy] Processing Image response (type: ${contentType}, size: ${bodyBuffer.length} bytes)`);
- res.setHeader('Content-Type', contentType); // Set the final Content-Type
- res.send(bodyBuffer);
-
- } else {
- // Other responses (HTML, other text, unknown binary, etc.): read as buffer and send safely
- const bodyBuffer = await response.buffer(); // Assuming 'fetch' response object has a .buffer() method or similar
- console.log(`[Hub Proxy] Processing Other response as buffer (type: ${contentType}, size: ${bodyBuffer.length} bytes)`);
- // Use original Content-Type if available, otherwise use octet-stream (already handled by default assignment)
- res.setHeader('Content-Type', contentType);
- res.send(bodyBuffer);
- }
- } catch (bodyError) {
- // If an error occurs while reading/processing the response body
- console.error("[Hub Proxy] Error reading/processing response body:", bodyError);
- if (!res.headersSent) {
- res.status(500).send({ error: 'Failed to process response body from hub server.' });
- } else {
- console.error("[Hub Proxy] Headers already sent, cannot send body error to client.");
- res.end();
- }
- return; // End the handler
+
+ for (const [key, value] of response.headers.entries()) {
+ res.setHeader(key, value);
}
+ res.status(response.status);
+
+ if (response.status >= 300 && response.status < 400) {
+ // Redirect handling (due to ‘/redirect/docs/lua’)
+ const redirectUrl = response.headers.get('location');
+ if (redirectUrl) {
+
+ if (redirectUrl.startsWith('http')) {
+
+ if (redirectUrl.startsWith(hubURL)) {
+ const newPath = redirectUrl.replace(hubURL, '/hub-proxy');
+ res.setHeader('location', newPath);
+ }
+
+ } else if (redirectUrl.startsWith('/')) {
+
+ res.setHeader('location', `/hub-proxy${redirectUrl}`);
+ }
+ }
+ return res.end();
+ }
+
+ await pipeline(response.body, res);
+
} catch (error) {
- // Fetch request itself failed or other exceptions
- console.error("[Hub Proxy] Request failed:", error);
+ console.error("[Hub Proxy] Error:", error);
if (!res.headersSent) {
- res.status(502).send({ error: 'Proxy failed to connect to or get response from the hub server.' });
+ res.status(502).send({ error: 'Proxy request failed: ' + error.message });
} else {
- console.error("[Hub Proxy] Headers already sent, cannot send connection error to client.");
res.end();
}
}
}
-app.get('/hub-proxy/*', hubProxyHandler);
-app.post('/hub-proxy/*', hubProxyHandler);
-app.put('/hub-proxy/*', hubProxyHandler);
-
app.get('/proxy', reverseProxyFunc_get);
app.get('/proxy2', reverseProxyFunc_get);
+app.get('/hub-proxy/*', hubProxyFunc);
app.post('/proxy', reverseProxyFunc);
app.post('/proxy2', reverseProxyFunc);
-
+app.post('/hub-proxy/*', hubProxyFunc);
app.get('/api/password', async(req, res)=> {
if(password === ''){
@@ -408,9 +365,6 @@ async function getHttpsOptions() {
const keyPath = path.join(sslPath, 'server.key');
const certPath = path.join(sslPath, 'server.crt');
- console.log(keyPath)
- console.log(certPath)
-
try {
await fs.access(keyPath);
diff --git a/src/lib/Others/AlertComp.svelte b/src/lib/Others/AlertComp.svelte
index 16273635..7801aee6 100644
--- a/src/lib/Others/AlertComp.svelte
+++ b/src/lib/Others/AlertComp.svelte
@@ -72,7 +72,7 @@
{
- if(e.origin.startsWith("https://sv.risuai.xyz") || e.origin.startsWith("http://127.0.0.1")){
+ if(e.origin.startsWith("https://sv.risuai.xyz") || e.origin.startsWith("http://127.0.0.1") || e.origin === window.location.origin){
if(e.data.msg.data.vaild && $alertStore.type === 'login'){
$alertStore = {
type: 'none',
diff --git a/src/lib/Setting/Pages/UserSettings.svelte b/src/lib/Setting/Pages/UserSettings.svelte
index 95a4a6c5..2cdcb012 100644
--- a/src/lib/Setting/Pages/UserSettings.svelte
+++ b/src/lib/Setting/Pages/UserSettings.svelte
@@ -19,7 +19,7 @@
{
- if(e.origin.startsWith("https://sv.risuai.xyz") || e.origin.startsWith("http://127.0.0.1")){
+ if(e.origin.startsWith("https://sv.risuai.xyz") || e.origin.startsWith("http://127.0.0.1") || e.origin === window.location.origin){
if(e.data.msg.type === 'drive'){
await loadRisuAccountData()
DBState.db.account.data.refresh_token = e.data.msg.data.refresh_token