Skip to content

Commit

Permalink
feat(gateway): 支持批量转换 rewrite-remote 中的 URL
Browse files Browse the repository at this point in the history
  • Loading branch information
geekdada committed Nov 27, 2019
1 parent 680b209 commit f589a83
Show file tree
Hide file tree
Showing 7 changed files with 367 additions and 201 deletions.
1 change: 1 addition & 0 deletions lib/gateway/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const createKoaApp = (surgioServer: SurgioServer): SurgioKoaApplication =
router.get('/get-artifact/:name', authMiddleware(), prepareArtifact(), surgioServer.koaGetArtifact.bind(surgioServer));
router.get('/list-artifact', authMiddleware(), surgioServer.koaListArtifact.bind(surgioServer));
router.get('/qx-script', surgioServer.processQuanXScript.bind(surgioServer));
router.get('/qx-rewrite-remote', surgioServer.processQuanXRewriteRemote.bind(surgioServer));
router.get('/robot.txt', ctx => {
ctx.body = 'User-agent: *\n' +
'Disallow: /';
Expand Down
48 changes: 46 additions & 2 deletions lib/gateway/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import path from "path";
import { PackageJson } from 'type-fest';
import legacyUrl from 'url';
import axios from 'axios';
import { transformQxRewriteRemote } from '../utils/qx-helper';
import TransfromScript from './utils/transform-script';

import getEngine from '../template';
Expand Down Expand Up @@ -161,17 +162,60 @@ export class Server {
responseType: 'stream',
})
.catch(err => {
throw createError(400, `请求文件时出错: ${err.message}`);
throw createError(500, `请求文件时出错: ${err.message}`);
});
const contentType: string = content.headers['content-type'];

if (
!contentType.includes('text/plain') ||
!contentType.includes('application/javascript')
) {
ctx.throw(400, '该文件不是一个可转换的脚本文件');
return;
}

const body = new TransfromScript(deviceIds);

content.data.pipe(body);

ctx.set('cache-control', 'max-age=3600');
ctx.set('content-disposition', 'attachment;filename=script.js');
ctx.set('cache-control', 'max-age=3600, s-maxage=3600');
ctx.body = body;
}

public async processQuanXRewriteRemote(ctx: Context): Promise<void> {
const { url, id: idFromUrl } = ctx.query;
const deviceIds = idFromUrl ? idFromUrl.split(',') : undefined;
const publicUrl = this.config.publicUrl;

if (!url) {
ctx.throw(400, 'invalid url');
return;
}

const content = await axios.request<string>({
url,
method: 'get',
responseType: 'text',
})
.catch(err => {
throw createError(500, `请求文件时出错: ${err.message}`);
});
const contentType: string = content.headers['content-type'];

if (
!contentType.includes('text/plain')
) {
ctx.throw(400, '该文件不是一个可转换的文件');
return;
}

ctx.set('content-type', contentType);
ctx.set('cache-control', 'max-age=3600, s-maxage=3600');
ctx.set('content-disposition', 'attachment;filename=rewrite-remote.conf');
ctx.body = transformQxRewriteRemote(content.data, publicUrl, deviceIds);
}

// istanbul ignore next
public fcErrorHandler(response: FcResponse, err: Error): void {
response.setStatusCode(500);
Expand Down
2 changes: 1 addition & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export interface CommandConfig {
};
readonly gateway?: {
readonly accessToken?: string;
readonly auth?: boolean;
auth?: boolean; // tslint:disable-line:readonly-keyword
},
readonly proxyTestUrl?: string;
readonly proxyTestInterval?: number;
Expand Down
34 changes: 34 additions & 0 deletions lib/utils/qx-helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { URL } from 'url';

export const transformQxRewriteRemote = (str: string, publicUrl: string, deviceIds?: ReadonlyArray<string>): string => {
return str.split('\n')
.map(item => {
if (
item.startsWith('#') ||
item.startsWith('//') ||
item.trim() === ''
) {
return item;
}

const rule = item.split(' ');

if (rule.indexOf('script-response-body') > -1) {
const scriptPath = rule[3];
const apiEndpoint = new URL(publicUrl);
apiEndpoint.pathname = '/qx-script';
apiEndpoint.searchParams.set('url', `${scriptPath}`);

if (deviceIds) {
apiEndpoint.searchParams.set('id', deviceIds.join(','));
}

rule[3] = apiEndpoint.toString();

return rule.join(' ');
}

return item;
})
.join('\n')
};
41 changes: 35 additions & 6 deletions test/gateway/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ test('auth', async t => {
const surgioServer = gateway.createSurgioServer(fixture);
const app = gateway.createKoaApp(surgioServer);

// @ts-ignore
app.surgioConfig.gateway.auth = true;

await request(app.callback())
Expand All @@ -171,13 +170,17 @@ test('qx-script', async t => {
const app = gateway.createKoaApp(surgioServer);

const res1 = await request(app.callback())
.get('/qx-script?url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js');
.get('/qx-script?url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js')
.expect(200);
const res2 = await request(app.callback())
.get('/qx-script?id=abcdef&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js');
.get('/qx-script?id=abcdef&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js')
.expect(200);
const res3 = await request(app.callback())
.get('/qx-script?id=abcdef,bcdefg&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js');
.get('/qx-script?id=abcdef,bcdefg&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js')
.expect(200);
const res4 = await request(app.callback())
.get('/qx-script?id=abcdef&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js');
.get('/qx-script?id=abcdef&url=https%3A%2F%2Fraw.githubusercontent.com%2Fcrossutility%2FQuantumult-X%2Fmaster%2Fsample-rewrite-with-script.js')
.expect(200);

t.snapshot(res1.body.toString());
t.snapshot(res2.body.toString());
Expand All @@ -192,11 +195,37 @@ test('qx-script error', async t => {

await request(app.callback())
.get('/qx-script?url=http://example.com/error')
.expect(400);
.expect(500);

await request(app.callback())
.get('/qx-script')
.expect(400);

t.pass();
});

test.only('qx-rewrite-remote', async t => {
const fixture = path.join(__dirname, '../fixture/gateway');
const surgioServer = gateway.createSurgioServer(fixture);
const app = gateway.createKoaApp(surgioServer);

const res = await request(app.callback())
.get('/qx-rewrite-remote?url=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf')
.expect(200)
.expect('content-type', 'text/plain; charset=utf-8')
.expect('cache-control', 'max-age=3600, s-maxage=3600');

t.snapshot(res.text);
});

test.only('qx-rewrite-remote with id', async t => {
const fixture = path.join(__dirname, '../fixture/gateway');
const surgioServer = gateway.createSurgioServer(fixture);
const app = gateway.createKoaApp(surgioServer);

const res = await request(app.callback())
.get('/qx-rewrite-remote?id=abcde,fghijk&url=https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Js.conf')
.expect(200);

t.snapshot(res.text);
});
Loading

0 comments on commit f589a83

Please sign in to comment.