Skip to content

Commit

Permalink
添加通用处理逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
汪航洋 committed Nov 10, 2023
1 parent 901f917 commit 55f8931
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 31 deletions.
31 changes: 11 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,18 @@
# React + TypeScript + Vite
# GOST V3 API Manage

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
官方的 web-ui 还没完成,先弄个简单的用一下,好过在 postMan 上捣腾;
纯前端的项目,部署在`github-pages`上, 放心[试用](https://blog.whyoop.com/gost-ui/);

Currently, two official plugins are available:
## 使用方式

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
1. 启动 API 服务

## Expanding the ESLint configuration
> `gost -api :18080` 或者 `gost -api admin:123456@:18080`
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
2. 打开 web 端管理地址 [点击打开](https://blog.whyoop.com/gost-ui/)

- Configure the top-level `parserOptions` property like this:
- API 地址 `http://IP:PORT`, 如果配置了`pathPrefix`,加上`pathPrefix`路径;
- (如果有) 填写 用户,密码;
- 点击 `连接` 按钮;

```js
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
```

- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
3. 管理面板,动态管理GOST
111 changes: 106 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { Col, Row } from "antd";
import { ProCard } from "@ant-design/pro-components";
import Ctx from "./uitls/ctx";
import { init, logout, useGolstCofnig } from "./uitls/server";
import { getConfig } from "./api";
import * as API from "./api";
import Home from "./Pages/Home";
import Services from "./Pages/Services";
import Chains from "./Pages/Chains";
import "./App.css";
import { configEvent } from "./uitls/events";
import PublicPage from "./Pages/PublicPage";

const colSpan = {
xs: 24,
Expand All @@ -18,13 +19,17 @@ const colSpan = {
xl: 12,
xxl: 8,
};
const colSpan1 = {
sm: 24,
xxl: 8,
};

function App() {
const gostInfo = useGolstCofnig();
const [gostConfig, setGostConfig] = useState<any>(null);

const updateConfig = useCallback(() => {
return getConfig().then((data) => {
return API.getConfig().then((data) => {
setGostConfig(data);
return data;
});
Expand All @@ -33,7 +38,7 @@ function App() {
useEffect(() => {
init();
const updateConfig = () => {
return getConfig().then((data) => {
return API.getConfig().then((data) => {
setGostConfig(data);
return data;
});
Expand Down Expand Up @@ -62,15 +67,111 @@ function App() {
<Row style={{ padding: 16, overflow: "hidden" }}>
<Row gutter={[16, 16]}>
<Col {...colSpan}>
<ProCard boxShadow title="Services">
<ProCard boxShadow title="服务(Service)">
<Services></Services>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="Chains">
<ProCard boxShadow title="转发链(Chain)">
<Chains></Chains>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="认证器(Auther)">
<PublicPage
title="认证器"
name="authers"
api={API.authers}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="准入控制器(Admission)">
<PublicPage
title="准入控制器"
name="admissions"
api={API.admissions}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="分流器(Bypass)">
<PublicPage
title="分流器"
name="bypass"
api={API.bypasses}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="主机映射器(Hosts)">
<PublicPage
title="主机映射器"
name="hosts"
api={API.hosts}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="跳跃点(Hop)">
<PublicPage
title="跳跃点"
name="hop"
api={API.hops}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="Ingress">
<PublicPage
title="Ingress"
name="ingresses"
api={API.ingresses}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan}>
<ProCard boxShadow title="域名解析器(Resolver)">
<PublicPage
title="Resolver"
name="resolvers"
api={API.resolvers}
></PublicPage>
</ProCard>
</Col>
<Col span={24}>
<ProCard boxShadow title="限速限流">
<Row gutter={[16, 16]}>
<Col {...colSpan1}>
<ProCard bordered title="流量速率限制">
<PublicPage
title=""
name="limiters"
api={API.limiters}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan1}>
<ProCard bordered title="请求速率限制">
<PublicPage
title=""
name="rlimiters"
api={API.rlimiters}
></PublicPage>
</ProCard>
</Col>
<Col {...colSpan1}>
<ProCard bordered title="并发连接数限制">
<PublicPage
title=""
name="climiters"
api={API.climiters}
></PublicPage>
</ProCard>
</Col>
</Row>
</ProCard>
</Col>
<Col span={24}>
<ProCard boxShadow title="All Config JSON">
<pre>{JSON.stringify(gostConfig, null, 4)}</pre>
Expand Down
97 changes: 97 additions & 0 deletions src/Pages/PublicPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { useContext, useEffect, useState } from "react";
import { Button, Popconfirm, Space, Table } from "antd";
import Ctx from "../uitls/ctx";
import * as API from "../api";
import JsonForm from "../components/Forms/Json";
import { ChainConfig } from "../api/types";

type Props = {
name: string;
title: string;
api: any;
keyName?: string;
};
const PublicPage: React.FC<Props> = (props) => {
const { name, title, api, keyName = "name" } = props;
const { gostConfig } = useContext(Ctx);
const dataList = (gostConfig as any)?.[name] || [];

const addService = async (servic: any) => {
const data = JSON.parse(servic);
await api.post(data);
};

const updateService = async (id: string, servic: any) => {
const data = JSON.parse(servic);
await api.put(id, data);
};

const deleteService = async (servic: any) => {
await api.delete(servic.name);
};

return (
<div>
<Table
size="small"
dataSource={dataList}
columns={[
{ title: keyName, dataIndex: keyName, width: 100 },
{
title: "详情",
ellipsis: true,
render: (value, record, index) => {
return JSON.stringify(record)
},
},
{
title: "操作",
width: 120,
render: (value, record, index) => {
return (
<Space size={"small"}>
<JsonForm
layoutType="ModalForm"
trigger={
<Button type="link" size={"small"}>
修改
</Button>
}
initialValues={{ value: JSON.stringify(record, null, 4) }}
onFinish={async (values: any) => {
const { value } = values;
await updateService(record.name, value);
return true;
}}
></JsonForm>
<Popconfirm
title="警告"
description="确定要删除吗?"
onConfirm={() => deleteService(record)}
>
<Button type="link" size={"small"}>
删除
</Button>
</Popconfirm>
</Space>
);
},
},
]}
></Table>
<div>
<JsonForm
title={`添加 ${title || ''}`}
layoutType="ModalForm"
trigger={<Button>新增</Button>}
onFinish={async (values: any) => {
const { value } = values;
await addService(value);
return true;
}}
></JsonForm>
</div>
</div>
);
};
export default PublicPage;
20 changes: 14 additions & 6 deletions src/Pages/Services.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useEffect, useState } from "react";
import { Button, Popconfirm, Space, Table } from "antd";
import qs from 'qs';
import qs from "qs";
// import { ProTable, ProCard } from "@ant-design/pro-components";
import Ctx from "../uitls/ctx";
import * as API from "../api";
Expand Down Expand Up @@ -56,11 +56,19 @@ const Services: React.FC = () => {
title: "详情",
ellipsis: true,
render: (value, record: ServiceConfig, index) => {
const {handler,listener, addr} = record;
const xy = handler.type === listener.type ? handler.type : handler.type + '+' + listener.type;
const auth = handler.auth ? handler.auth.username + ':' + handler.auth.password + '@' : '';
const metadata = handler.metadata ? qs.stringify(handler.metadata) : '';
return `${xy}://${auth}${addr}?${metadata}` ;
const { handler, listener, addr, forwarder } = record;
const xy =
handler.type === listener.type
? handler.type
: handler.type + "+" + listener.type;
const auth = handler.auth
? handler.auth.username + ":" + handler.auth.password + "@"
: "";
const metadata = handler.metadata
? qs.stringify(handler.metadata)
: "";
// const targets = forwarder // TODO:
return `${xy}://${auth}${addr}${metadata ? "?" + metadata : ""}`;
},
},
{
Expand Down
59 changes: 59 additions & 0 deletions src/uitls/templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export default {
Services: [
{
label: "端口转发",
cli: "-L tcp://:80/:8080",
json: `
{
"name": "service-0",
"addr": ":80",
"handler": {
"type": "tcp"
},
"listener": {
"type": "tcp"
},
"forwarder": {
"nodes": [
{
"name": "target-0",
"addr": ":8080"
}
]
}
}`,
},
{
label: "代理转发",
cli: "-L socks5://:1080 -F socks5://xxx.com:1080",
json: `
{
"name": "service-0",
"addr": ":1080",
"handler": {
"type": "socks5",
"chain": "chain-0"
},
"listener": {
"type": "tcp"
}
}`,
},
{
label: "代理转发",
},
],
Authers: [
{
label: "默认模板",
json: `
{
"name": "auther-0",
"auths": [
{ "username": "user1", "password": "pass1" },
{ "username": "user2", "password": "pass2" },
],
}`,
},
],
};

0 comments on commit 55f8931

Please sign in to comment.