mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-23 15:31:26 +00:00
support select CA file extension
This commit is contained in:
parent
d9548ae7cf
commit
67151c071b
@ -1,7 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const DEFAULT_WEB_PORT = 8002; // port for web interface
|
|
||||||
|
|
||||||
const express = require('express'),
|
const express = require('express'),
|
||||||
url = require('url'),
|
url = require('url'),
|
||||||
bodyParser = require('body-parser'),
|
bodyParser = require('body-parser'),
|
||||||
@ -16,9 +14,13 @@ const express = require('express'),
|
|||||||
ip = require('ip'),
|
ip = require('ip'),
|
||||||
compress = require('compression');
|
compress = require('compression');
|
||||||
|
|
||||||
|
const DEFAULT_WEB_PORT = 8002; // port for web interface
|
||||||
|
|
||||||
const packageJson = require('../package.json');
|
const packageJson = require('../package.json');
|
||||||
|
|
||||||
const MAX_CONTENT_SIZE = 1024 * 2000; // 2000kb
|
const MAX_CONTENT_SIZE = 1024 * 2000; // 2000kb
|
||||||
|
|
||||||
|
const certFileTypes = ['crt', 'cer', 'pem', 'der'];
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
@ -204,8 +206,9 @@ class webInterface extends events.EventEmitter {
|
|||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
const _crtFilePath = certMgr.getRootCAFilePath();
|
const _crtFilePath = certMgr.getRootCAFilePath();
|
||||||
if (_crtFilePath) {
|
if (_crtFilePath) {
|
||||||
|
const fileType = certFileTypes.indexOf(req.query.type) !== -1 ? req.query.type : 'crt';
|
||||||
res.setHeader('Content-Type', 'application/x-x509-ca-cert');
|
res.setHeader('Content-Type', 'application/x-x509-ca-cert');
|
||||||
res.setHeader('Content-Disposition', 'attachment; filename="rootCA.crt"');
|
res.setHeader('Content-Disposition', `attachment; filename="rootCA.${fileType}"`);
|
||||||
res.end(fs.readFileSync(_crtFilePath, { encoding: null }));
|
res.end(fs.readFileSync(_crtFilePath, { encoding: null }));
|
||||||
} else {
|
} else {
|
||||||
res.setHeader('Content-Type', 'text/html');
|
res.setHeader('Content-Type', 'text/html');
|
||||||
@ -213,25 +216,12 @@ class webInterface extends events.EventEmitter {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//make qr code
|
|
||||||
app.get('/qr', (req, res) => {
|
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
||||||
res.setHeader('Content-Type', 'text/html');
|
|
||||||
|
|
||||||
const qr = qrCode.qrcode(4, 'M');
|
|
||||||
const targetUrl = req.protocol + '://' + req.get('host');
|
|
||||||
qr.addData(targetUrl);
|
|
||||||
qr.make();
|
|
||||||
const qrImageTag = qr.createImgTag(4);
|
|
||||||
const resDom = '<a href="__url"> __img <br> click or scan qr code to start client </a>'.replace(/__url/, targetUrl).replace(/__img/, qrImageTag);
|
|
||||||
res.end(resDom);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.get('/api/getQrCode', (req, res) => {
|
app.get('/api/getQrCode', (req, res) => {
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
|
||||||
|
const fileType = certFileTypes.indexOf(req.query.type) !== -1 ? req.query.type : 'crt';
|
||||||
const qr = qrCode.qrcode(4, 'M');
|
const qr = qrCode.qrcode(4, 'M');
|
||||||
const targetUrl = req.protocol + '://' + req.get('host') + '/fetchCrtFile';
|
const targetUrl = req.protocol + '://' + req.get('host') + '/fetchCrtFile?type=' + fileType;
|
||||||
const isRootCAFileExists = certMgr.isRootCAFileExists();
|
const isRootCAFileExists = certMgr.isRootCAFileExists();
|
||||||
|
|
||||||
qr.addData(targetUrl);
|
qr.addData(targetUrl);
|
||||||
|
44
test/spec_lib/webInterface.js
Normal file
44
test/spec_lib/webInterface.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const WebInterface = require('../../lib/webInterface.js');
|
||||||
|
const Recorder = require('../../lib/recorder');
|
||||||
|
const { directGet } = require('../util/HttpUtil.js');
|
||||||
|
|
||||||
|
describe('WebInterface server', () => {
|
||||||
|
let webServer = null;
|
||||||
|
let webHost = 'http://127.0.0.1:8002';
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
const recorder = new Recorder();
|
||||||
|
webServer = new WebInterface({
|
||||||
|
webPort: 8002,
|
||||||
|
}, recorder);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
webServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support change CA extensions in /getQrCode', done => {
|
||||||
|
const certFileTypes = ['crt', 'cer', 'pem', 'der'];
|
||||||
|
const tasks = certFileTypes.map((type) => {
|
||||||
|
return directGet(`${webHost}/api/getQrCode`, { type })
|
||||||
|
.then(res => {
|
||||||
|
const body = JSON.parse(res.body);
|
||||||
|
expect(body.qrImgDom).toMatch('<img src="data:image/');
|
||||||
|
expect(body.url).toBe(`${webHost}/fetchCrtFile?type=${type}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(tasks)
|
||||||
|
.then(done)
|
||||||
|
.catch(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fallback to .crt file in /getQrCode', done => {
|
||||||
|
directGet(`${webHost}/api/getQrCode`, { type: 'unkonw' })
|
||||||
|
.then(res => {
|
||||||
|
expect(JSON.parse(res.body).url).toBe(`${webHost}/fetchCrtFile?type=crt`);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(done);
|
||||||
|
});
|
||||||
|
});
|
@ -5,26 +5,29 @@
|
|||||||
|
|
||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import ClassBind from 'classnames/bind';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { message, Button, Spin } from 'antd';
|
import { message, Button, Spin, Select } from 'antd';
|
||||||
import ResizablePanel from 'component/resizable-panel';
|
import ResizablePanel from 'component/resizable-panel';
|
||||||
import { hideRootCA, updateIsRootCAExists } from 'action/globalStatusAction';
|
import { hideRootCA, updateIsRootCAExists } from 'action/globalStatusAction';
|
||||||
import { MenuKeyMap } from 'common/Constant';
|
import { MenuKeyMap } from 'common/Constant';
|
||||||
import { getJSON, ajaxGet, postJSON } from 'common/ApiUtil';
|
import { getJSON, postJSON } from 'common/ApiUtil';
|
||||||
|
|
||||||
import Style from './download-root-ca.less';
|
import Style from './download-root-ca.less';
|
||||||
import CommonStyle from '../style/common.less';
|
import CommonStyle from '../style/common.less';
|
||||||
|
|
||||||
|
const certFileTypes = ['crt', 'cer', 'pem', 'der'];
|
||||||
|
|
||||||
class DownloadRootCA extends React.Component {
|
class DownloadRootCA extends React.Component {
|
||||||
constructor () {
|
constructor () {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
loadingCAQr: false,
|
loadingCAQr: false,
|
||||||
generatingCA: false
|
generatingCA: false,
|
||||||
|
fileType: certFileTypes[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onClose = this.onClose.bind(this);
|
this.onClose = this.onClose.bind(this);
|
||||||
|
this.onFileTypeChange = this.onFileTypeChange.bind(this);
|
||||||
this.getQrCodeContent = this.getQrCodeContent.bind(this);
|
this.getQrCodeContent = this.getQrCodeContent.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +41,7 @@ class DownloadRootCA extends React.Component {
|
|||||||
loadingCAQr: true
|
loadingCAQr: true
|
||||||
});
|
});
|
||||||
|
|
||||||
getJSON('/api/getQrCode')
|
getJSON('/api/getQrCode', { type: this.state.fileType })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loadingCAQr: false,
|
loadingCAQr: false,
|
||||||
@ -57,12 +60,33 @@ class DownloadRootCA extends React.Component {
|
|||||||
this.props.dispatch(hideRootCA());
|
this.props.dispatch(hideRootCA());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFileTypeChange (value) {
|
||||||
|
this.setState({
|
||||||
|
fileType: value
|
||||||
|
}, () => {
|
||||||
|
this.fetchData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getQrCodeContent () {
|
getQrCodeContent () {
|
||||||
const imgDomContent = { __html: this.state.CAQrCodeImageDom };
|
const imgDomContent = { __html: this.state.CAQrCodeImageDom };
|
||||||
const content = (
|
const content = (
|
||||||
<div className={Style.qrCodeWrapper} >
|
<div className={Style.qrCodeWrapper} >
|
||||||
<div dangerouslySetInnerHTML={imgDomContent} />
|
<div dangerouslySetInnerHTML={imgDomContent} />
|
||||||
<span>Scan to download rootCA.crt to your Phone</span>
|
<div>Scan to download rootCA.{this.state.fileType} to your Phone</div>
|
||||||
|
<div>You can change the CA's file extension:
|
||||||
|
<Select
|
||||||
|
defaultValue={this.state.fileType}
|
||||||
|
className={Style.fileSelect}
|
||||||
|
onChange={this.onFileTypeChange}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
certFileTypes.map(key => (
|
||||||
|
<Option key={key} value={key}>{key}</Option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -71,7 +95,6 @@ class DownloadRootCA extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getGenerateRootCADiv () {
|
getGenerateRootCADiv () {
|
||||||
|
|
||||||
const doToggleRemoteIntercept = () => {
|
const doToggleRemoteIntercept = () => {
|
||||||
postJSON('/api/generateRootCA')
|
postJSON('/api/generateRootCA')
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
@ -127,8 +150,8 @@ class DownloadRootCA extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={Style.buttons} >
|
<div className={Style.buttons} >
|
||||||
<a href="/fetchCrtFile" target="_blank">
|
<a href={`/fetchCrtFile?type=${this.state.fileType}`} target="_blank">
|
||||||
<Button type="primary" size="large" > Download </Button>
|
<Button type="primary" size="large" >Download</Button>
|
||||||
</a>
|
</a>
|
||||||
<span className={Style.tipSpan} >Or click the button to download.</span>
|
<span className={Style.tipSpan} >Or click the button to download.</span>
|
||||||
</div>
|
</div>
|
||||||
@ -146,7 +169,6 @@ class DownloadRootCA extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<ResizablePanel onClose={this.onClose} visible={panelVisible} >
|
<ResizablePanel onClose={this.onClose} visible={panelVisible} >
|
||||||
{this.props.globalStatus.isRootCAFileExists ? this.getDownloadDiv() : this.getGenerateRootCADiv()}
|
{this.props.globalStatus.isRootCAFileExists ? this.getDownloadDiv() : this.getGenerateRootCADiv()}
|
||||||
|
|
||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -55,4 +55,9 @@
|
|||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileSelect {
|
||||||
|
width: 60px;
|
||||||
|
margin-left: 8px;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user