diff --git a/client/src/actions/index.js b/client/src/actions/index.js
index c4700198..862c36cf 100644
--- a/client/src/actions/index.js
+++ b/client/src/actions/index.js
@@ -420,3 +420,36 @@ export const setUpstream = url => async (dispatch) => {
dispatch(setUpstreamFailure());
}
};
+
+export const testUpstreamRequest = createAction('TEST_UPSTREAM_REQUEST');
+export const testUpstreamFailure = createAction('TEST_UPSTREAM_FAILURE');
+export const testUpstreamSuccess = createAction('TEST_UPSTREAM_SUCCESS');
+
+export const testUpstream = servers => async (dispatch) => {
+ dispatch(testUpstreamRequest());
+ try {
+ if (servers.length > 0) {
+ const upstreamResponse = await apiClient.testUpstream(servers);
+
+ const testMessages = Object.keys(upstreamResponse).map((key) => {
+ const message = upstreamResponse[key];
+ if (message !== 'OK') {
+ dispatch(addErrorToast({ error: `Server "${key}": could not be used, please check that you've written it correctly` }));
+ }
+ return message;
+ });
+
+ if (testMessages.every(message => message === testMessages[0])) {
+ dispatch(addSuccessToast('All servers is OK'));
+ }
+
+ dispatch(testUpstreamSuccess());
+ } else {
+ dispatch(addErrorToast({ error: 'No servers specified' }));
+ dispatch(testUpstreamFailure());
+ }
+ } catch (error) {
+ dispatch(addErrorToast({ error }));
+ dispatch(testUpstreamFailure());
+ }
+};
diff --git a/client/src/api/Api.js b/client/src/api/Api.js
index 4408eb51..b56d4307 100644
--- a/client/src/api/Api.js
+++ b/client/src/api/Api.js
@@ -31,6 +31,7 @@ export default class Api {
GLOBAL_QUERY_LOG_ENABLE = { path: 'querylog_enable', method: 'POST' };
GLOBAL_QUERY_LOG_DISABLE = { path: 'querylog_disable', method: 'POST' };
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstream_dns', method: 'POST' };
+ GLOBAL_TEST_UPSTREAM_DNS = { path: 'test_upstream_dns', method: 'POST' };
GLOBAL_VERSION = { path: 'version.json', method: 'GET' };
restartGlobalFiltering() {
@@ -108,6 +109,15 @@ export default class Api {
return this.makeRequest(path, method, config);
}
+ testUpstream(servers) {
+ const { path, method } = this.GLOBAL_TEST_UPSTREAM_DNS;
+ const config = {
+ data: servers,
+ header: { 'Content-Type': 'text/plain' },
+ };
+ return this.makeRequest(path, method, config);
+ }
+
getGlobalVersion() {
const { path, method } = this.GLOBAL_VERSION;
return this.makeRequest(path, method);
diff --git a/client/src/components/Filters/UserRules.js b/client/src/components/Filters/UserRules.js
index 58cc059d..c748c3bc 100644
--- a/client/src/components/Filters/UserRules.js
+++ b/client/src/components/Filters/UserRules.js
@@ -27,7 +27,7 @@ export default class UserRules extends Component {
type="submit"
onClick={this.handleSubmit}
>
- Apply...
+ Apply
diff --git a/client/src/components/Settings/Upstream.js b/client/src/components/Settings/Upstream.js
index a2645854..db43943e 100644
--- a/client/src/components/Settings/Upstream.js
+++ b/client/src/components/Settings/Upstream.js
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
+import classnames from 'classnames';
import Card from '../ui/Card';
export default class Upstream extends Component {
@@ -13,7 +14,16 @@ export default class Upstream extends Component {
this.props.handleUpstreamSubmit();
};
+ handleTest = () => {
+ this.props.handleUpstreamTest();
+ }
+
render() {
+ const testButtonClass = classnames({
+ 'btn btn-primary btn-standart mr-2': true,
+ 'btn btn-primary btn-standart mr-2 btn-loading': this.props.processingTestUpstream,
+ });
+
return (