[skip ci] Dev improvement (#1324)
* added ServerSettings for proxy server * fix: duplicated credentials headers * simplify settings request * feat: use user agent * clean up * fix: missing status code * update plugin template
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
import { fetchApi } from '@libs/fetch';
|
import { fetchApi, fetchProto, fetchText } from '@libs/fetch';
|
||||||
import { Plugin } from '@typings/plugin';
|
import { Plugin } from '@typings/plugin';
|
||||||
import { Filters } from '@libs/filterInputs';
|
import { Filters } from '@libs/filterInputs';
|
||||||
import { load as loadCheerio } from 'cheerio';
|
import { load as loadCheerio } from 'cheerio';
|
||||||
import { defaultCover } from '@libs/defaultCover';
|
import { defaultCover } from '@libs/defaultCover';
|
||||||
import { NovelStatus } from '@libs/novelStatus';
|
import { NovelStatus } from '@libs/novelStatus';
|
||||||
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
|
// import { isUrlAbsolute } from '@libs/isAbsoluteUrl';
|
||||||
|
// import { storage, localStorage, sessionStorage } from '@libs/storage';
|
||||||
|
// import { encode, decode } from 'urlencode';
|
||||||
|
// import dayjs from 'dayjs';
|
||||||
|
// import { Parser } from 'htmlparser2';
|
||||||
|
|
||||||
class TemplatePlugin implements Plugin.PluginBase {
|
class TemplatePlugin implements Plugin.PluginBase {
|
||||||
id = '';
|
id = '';
|
||||||
@@ -15,6 +19,9 @@ class TemplatePlugin implements Plugin.PluginBase {
|
|||||||
filters: Filters | undefined = undefined;
|
filters: Filters | undefined = undefined;
|
||||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
||||||
|
|
||||||
|
//flag indicates whether access to LocalStorage, SesesionStorage is required.
|
||||||
|
webStorageUtilized?: boolean;
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
{
|
{
|
||||||
|
|||||||
+65
-76
@@ -2,22 +2,24 @@ import http from 'http';
|
|||||||
import httpProxy from 'http-proxy';
|
import httpProxy from 'http-proxy';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
|
|
||||||
const CLIENT_HOST = 'http://localhost:3000';
|
|
||||||
const proxy = httpProxy.createProxyServer({});
|
const proxy = httpProxy.createProxyServer({});
|
||||||
let request_mode = 'proxy';
|
const ServerSettings = {
|
||||||
|
CLIENT_HOST: 'http://localhost:3000',
|
||||||
const disAllowedRequestHeaders = [
|
fetchMode: 'proxy',
|
||||||
'sec-ch-ua',
|
cookies: null,
|
||||||
'sec-ch-ua-mobile',
|
disAllowedRequestHeaders: [
|
||||||
'sec-ch-ua-platform',
|
'sec-ch-ua',
|
||||||
'sec-fetch-site',
|
'sec-ch-ua-mobile',
|
||||||
'origin',
|
'sec-ch-ua-platform',
|
||||||
'sec-fetch-site',
|
'sec-fetch-site',
|
||||||
'sec-fetch-dest',
|
'origin',
|
||||||
'pragma',
|
'sec-fetch-site',
|
||||||
];
|
'sec-fetch-dest',
|
||||||
|
'pragma',
|
||||||
const disAllowResponseHeaders = ['link', 'set-cookie', 'set-cookie2'];
|
],
|
||||||
|
disAllowResponseHeaders: ['link', 'set-cookie', 'set-cookie2'],
|
||||||
|
useUserAgent: true,
|
||||||
|
};
|
||||||
|
|
||||||
const proxyRequest = (req, res) => {
|
const proxyRequest = (req, res) => {
|
||||||
const _url = new URL(req.url);
|
const _url = new URL(req.url);
|
||||||
@@ -31,10 +33,14 @@ headers:`,
|
|||||||
console.log('\t', '\x1b[32m', name + ':', '\x1b[37m', value);
|
console.log('\t', '\x1b[32m', name + ':', '\x1b[37m', value);
|
||||||
});
|
});
|
||||||
console.log('\x1b[36m', '----------------');
|
console.log('\x1b[36m', '----------------');
|
||||||
if (request_mode === 'curl') {
|
if (ServerSettings.fetchMode === 'curl') {
|
||||||
//i mean if it works it works i guess, better than nothing
|
//i mean if it works it works i guess, better than nothing
|
||||||
let curl = `curl '${_url.href}' -H 'User-Agent: ${req.headers['user-agent']}'`;
|
let curl = `curl '${_url.href}'`;
|
||||||
if (temp_cookies) curl += ` -H 'Cookie: ${temp_cookies}'`;
|
if (ServerSettings.useUserAgent) {
|
||||||
|
curl += ` -H 'User-Agent: ${req.headers['user-agent']}'`;
|
||||||
|
}
|
||||||
|
if (ServerSettings.cookies)
|
||||||
|
curl += ` -H 'Cookie: ${ServerSettings.cookies}'`;
|
||||||
if (req.headers.origin2) curl += ` -H 'Origin: ${req.headers.origin2}'`;
|
if (req.headers.origin2) curl += ` -H 'Origin: ${req.headers.origin2}'`;
|
||||||
|
|
||||||
console.log('Running curl command:', curl);
|
console.log('Running curl command:', curl);
|
||||||
@@ -51,10 +57,7 @@ headers:`,
|
|||||||
exec(curl, options, (error, stdout, stderr) => {
|
exec(curl, options, (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error(`exec error: ${error}`);
|
console.error(`exec error: ${error}`);
|
||||||
res.writeHead(500, {
|
res.statusCode = 500;
|
||||||
'Access-Control-Allow-Origin': CLIENT_HOST,
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
});
|
|
||||||
res.write(`exec error: ${error}`);
|
res.write(`exec error: ${error}`);
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@@ -62,27 +65,23 @@ headers:`,
|
|||||||
if (stderr) {
|
if (stderr) {
|
||||||
console.error(`stderr: ${stderr}`);
|
console.error(`stderr: ${stderr}`);
|
||||||
}
|
}
|
||||||
res.writeHead(200, {
|
res.statusCode = 200;
|
||||||
'Access-Control-Allow-Origin': CLIENT_HOST,
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
});
|
|
||||||
res.write(stdout);
|
res.write(stdout);
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
} else if (request_mode === 'node-fetch') {
|
} else if (ServerSettings.fetchMode === 'node-fetch') {
|
||||||
fetch(_url.href, {
|
fetch(_url.href, {
|
||||||
'headers': {
|
'headers': {
|
||||||
'cookie': temp_cookies,
|
'cookie': ServerSettings.cookies,
|
||||||
'origin': req.headers.origin2,
|
'origin': req.headers.origin2,
|
||||||
'user-agent': req.headers['user-agent'],
|
'user-agent': ServerSettings.useUserAgent
|
||||||
|
? req.headers['user-agent']
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res2 => res2.text())
|
.then(res2 => res2.text())
|
||||||
.then(res2 => {
|
.then(res2 => {
|
||||||
res.writeHead(200, {
|
res.statusCode = 200;
|
||||||
'Access-Control-Allow-Origin': CLIENT_HOST,
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
});
|
|
||||||
res.write(res2);
|
res.write(res2);
|
||||||
res.end();
|
res.end();
|
||||||
})
|
})
|
||||||
@@ -91,7 +90,7 @@ headers:`,
|
|||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
} else if (request_mode === 'proxy') {
|
} else if (ServerSettings.fetchMode === 'proxy') {
|
||||||
proxy.web(req, res, {
|
proxy.web(req, res, {
|
||||||
target: _url.origin,
|
target: _url.origin,
|
||||||
selfHandleResponse: true,
|
selfHandleResponse: true,
|
||||||
@@ -128,15 +127,13 @@ proxy.on('proxyRes', function (proxyRes, req, res) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const _header in proxyRes.headers) {
|
for (const _header in proxyRes.headers) {
|
||||||
if (!disAllowResponseHeaders.includes(_header)) {
|
if (!ServerSettings.disAllowResponseHeaders.includes(_header)) {
|
||||||
res.setHeader(_header, proxyRes.headers[_header]);
|
res.setHeader(_header, proxyRes.headers[_header]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const _header in disAllowedRequestHeaders) {
|
for (const _header in ServerSettings.disAllowedRequestHeaders) {
|
||||||
delete proxyRes.headers[_header];
|
delete proxyRes.headers[_header];
|
||||||
}
|
}
|
||||||
res.setHeader('Access-Control-Allow-Origin', CLIENT_HOST);
|
|
||||||
res.setHeader('Access-Control-Allow-Credentials', true);
|
|
||||||
proxyRes.on('data', function (chunk) {
|
proxyRes.on('data', function (chunk) {
|
||||||
res.write(chunk);
|
res.write(chunk);
|
||||||
});
|
});
|
||||||
@@ -145,31 +142,25 @@ proxy.on('proxyRes', function (proxyRes, req, res) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var temp_cookies = null;
|
const settingsHandler = (req, res) => {
|
||||||
|
let str = '';
|
||||||
const cookiesHandler = (req, res) => {
|
|
||||||
let cookies = '';
|
|
||||||
res.setHeader('Access-Control-Allow-Origin', CLIENT_HOST);
|
|
||||||
res.setHeader('Access-Control-Allow-Credentials', true);
|
|
||||||
req.on('data', chunk => {
|
req.on('data', chunk => {
|
||||||
cookies += chunk;
|
str += chunk;
|
||||||
});
|
});
|
||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
temp_cookies = cookies;
|
try {
|
||||||
res.end();
|
const settings = JSON.parse(str);
|
||||||
});
|
for (let setting in settings) {
|
||||||
};
|
ServerSettings[setting] = settings[setting];
|
||||||
|
}
|
||||||
const fetchModeHandler = (req, res) => {
|
res.statusCode = 200;
|
||||||
let fetchMode = '';
|
res.setHeader('Content-Type', 'application/json');
|
||||||
res.setHeader('Access-Control-Allow-Origin', CLIENT_HOST);
|
res.write(JSON.stringify(ServerSettings));
|
||||||
res.setHeader('Access-Control-Allow-Credentials', true);
|
} catch {
|
||||||
req.on('data', chunk => {
|
res.statusCode = 400;
|
||||||
fetchMode += chunk;
|
} finally {
|
||||||
});
|
res.end();
|
||||||
req.on('end', () => {
|
}
|
||||||
request_mode = fetchMode;
|
|
||||||
res.end();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -190,37 +181,35 @@ http
|
|||||||
);
|
);
|
||||||
delete req.headers['access-control-request-headers'];
|
delete req.headers['access-control-request-headers'];
|
||||||
}
|
}
|
||||||
if (path === 'cookies') {
|
res.setHeader('Access-Control-Allow-Origin', ServerSettings.CLIENT_HOST);
|
||||||
cookiesHandler(req, res);
|
res.setHeader('Access-Control-Allow-Credentials', true);
|
||||||
} else if (path === 'fetchMode') {
|
if (req.method === 'OPTIONS') {
|
||||||
fetchModeHandler(req, res);
|
res.statusCode = 200;
|
||||||
|
res.end();
|
||||||
|
} else if (path === 'settings') {
|
||||||
|
settingsHandler(req, res);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const _url = new URL(path);
|
const _url = new URL(path);
|
||||||
for (const _header in req.headers) {
|
for (const _header in req.headers) {
|
||||||
if (
|
if (
|
||||||
req.headers[_header]?.includes('localhost') ||
|
req.headers[_header]?.includes('localhost') ||
|
||||||
disAllowedRequestHeaders.includes(_header)
|
ServerSettings.disAllowedRequestHeaders.includes(_header)
|
||||||
) {
|
) {
|
||||||
delete req.headers[_header];
|
delete req.headers[_header];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req.headers['sec-fetch-mode'] = 'cors';
|
req.headers['sec-fetch-mode'] = 'cors';
|
||||||
if (temp_cookies) {
|
if (ServerSettings.cookies) {
|
||||||
req.headers['cookie'] = temp_cookies;
|
req.headers['cookie'] = ServerSettings.cookies;
|
||||||
|
}
|
||||||
|
if (!ServerSettings.useUserAgent) {
|
||||||
|
delete req.headers['user-agent'];
|
||||||
}
|
}
|
||||||
req.headers.host = _url.host;
|
req.headers.host = _url.host;
|
||||||
req.url = _url.toString();
|
req.url = _url.toString();
|
||||||
res.statusCode = 200;
|
res.statusCode = 200;
|
||||||
if (req.method === 'OPTIONS') {
|
proxyRequest(req, res);
|
||||||
res.writeHead(200, {
|
|
||||||
'Access-Control-Allow-Origin': CLIENT_HOST,
|
|
||||||
'Access-Control-Allow-Credentials': true,
|
|
||||||
});
|
|
||||||
res.end();
|
|
||||||
} else {
|
|
||||||
proxyRequest(req, res);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('\x1b[31m', '----------ERRROR----------');
|
console.log('\x1b[31m', '----------ERRROR----------');
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
TextField,
|
TextField,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import Checkbox from '@mui/material/Checkbox';
|
||||||
import useDebounce from '@hooks/useDebounce';
|
import useDebounce from '@hooks/useDebounce';
|
||||||
|
|
||||||
export default function HeadersSection() {
|
export default function HeadersSection() {
|
||||||
@@ -15,36 +16,34 @@ export default function HeadersSection() {
|
|||||||
const [cookies, setCookies] = useState('');
|
const [cookies, setCookies] = useState('');
|
||||||
const debounceCookies = useDebounce(cookies, 500);
|
const debounceCookies = useDebounce(cookies, 500);
|
||||||
const [fetchMode, setFetchMode] = useState('proxy');
|
const [fetchMode, setFetchMode] = useState('proxy');
|
||||||
const [alertVisible, setAlertVisble] = useState('');
|
const [alertVisible, setAlertVisble] = useState(false);
|
||||||
|
const [useUserAgent, setUseUserAgent] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (alertVisible) {
|
if (alertVisible) {
|
||||||
const id = setTimeout(() => setAlertVisble(''), 1000);
|
const id = setTimeout(() => setAlertVisble(false), 1000);
|
||||||
return () => clearTimeout(id);
|
return () => clearTimeout(id);
|
||||||
}
|
}
|
||||||
}, [alertVisible]);
|
}, [alertVisible]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
fetch('cookies', {
|
fetch('settings', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: debounceCookies,
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
cookies: debounceCookies,
|
||||||
|
fetchMode: fetchMode,
|
||||||
|
useUserAgent,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
.then(() => setAlertVisble('Cookies updated'))
|
.then(() => setAlertVisble(true))
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}, [debounceCookies]);
|
}, [debounceCookies, fetchMode, useUserAgent]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setLoading(true);
|
|
||||||
fetch('fetchMode', {
|
|
||||||
method: 'POST',
|
|
||||||
body: fetchMode,
|
|
||||||
})
|
|
||||||
.then(() => setAlertVisble('Fetch mode updated'))
|
|
||||||
.finally(() => setLoading(false));
|
|
||||||
}, [fetchMode]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AccordionContainer title="Headers" loading={loading}>
|
<AccordionContainer title="Settings" loading={loading}>
|
||||||
{alertVisible ? (
|
{alertVisible ? (
|
||||||
<Alert
|
<Alert
|
||||||
sx={{
|
sx={{
|
||||||
@@ -54,20 +53,27 @@ export default function HeadersSection() {
|
|||||||
right: 0,
|
right: 0,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{alertVisible}
|
Settings updated
|
||||||
</Alert>
|
</Alert>
|
||||||
) : null}
|
) : null}
|
||||||
<TextField
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
||||||
size="small"
|
<TextField
|
||||||
InputProps={{
|
size="small"
|
||||||
startAdornment: (
|
InputProps={{
|
||||||
<InputAdornment position="start">Headers</InputAdornment>
|
startAdornment: (
|
||||||
),
|
<InputAdornment position="start">User Agent</InputAdornment>
|
||||||
}}
|
),
|
||||||
disabled
|
}}
|
||||||
value={navigator.userAgent}
|
disabled
|
||||||
sx={{ width: '100%' }}
|
value={navigator.userAgent}
|
||||||
/>
|
sx={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
size="large"
|
||||||
|
checked={useUserAgent}
|
||||||
|
onChange={e => setUseUserAgent(e.target.checked)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
<Box sx={{ height: 10 }} />
|
<Box sx={{ height: 10 }} />
|
||||||
<TextField
|
<TextField
|
||||||
size="small"
|
size="small"
|
||||||
|
|||||||
Reference in New Issue
Block a user