1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-02-28 19:14:13 +08:00

feat: 反向代理增加编辑功能

This commit is contained in:
zhengkunwang223 2023-04-24 11:29:48 +08:00 committed by zhengkunwang223
parent d900b52a50
commit 2dd88364f8
7 changed files with 159 additions and 35 deletions

View File

@ -19,7 +19,6 @@ import (
"path" "path"
"reflect" "reflect"
"regexp" "regexp"
"strconv"
"strings" "strings"
"time" "time"
@ -1164,7 +1163,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
switch req.Operate { switch req.Operate {
case "create": case "create":
_ = fileOp.DeleteFile(includePath) _ = fileOp.DeleteFile(includePath)
case "update": case "edit":
_ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755) _ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755)
} }
} }
@ -1175,7 +1174,7 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
switch req.Operate { switch req.Operate {
case "create": case "create":
config = parser.NewStringParser(string(nginx_conf.Proxy)).Parse() config = parser.NewStringParser(string(nginx_conf.Proxy)).Parse()
case "update": case "edit":
par, err = parser.NewParser(includePath) par, err = parser.NewParser(includePath)
if err != nil { if err != nil {
return return
@ -1193,6 +1192,11 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
backPath := path.Join(includeDir, backName) backPath := path.Join(includeDir, backName)
_ = fileOp.Rename(includePath, backPath) _ = fileOp.Rename(includePath, backPath)
return updateNginxConfig(constant.NginxScopeServer, nil, &website) return updateNginxConfig(constant.NginxScopeServer, nil, &website)
case "enable":
backName := fmt.Sprintf("%s.bak", req.Name)
backPath := path.Join(includeDir, backName)
_ = fileOp.Rename(backPath, includePath)
return updateNginxConfig(constant.NginxScopeServer, nil, &website)
} }
config.FilePath = includePath config.FilePath = includePath
directives := config.Directives directives := config.Directives
@ -1205,15 +1209,14 @@ func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error)
location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost}) location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost})
location.ChangePath(req.Modifier, req.Match) location.ChangePath(req.Modifier, req.Match)
if req.Cache { if req.Cache {
location.AddCache(strconv.Itoa(req.CacheTime) + req.CacheUnit) location.AddCache(req.CacheTime, req.CacheUnit)
} else { } else {
location.RemoveCache() location.RemoveCache()
} }
if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
return buserr.WithErr(constant.ErrUpdateBuWebsite, err) return buserr.WithErr(constant.ErrUpdateBuWebsite, err)
} }
nginxInclude := path.Join("www", "sites", website.Alias, "proxy", "*.conf") nginxInclude := fmt.Sprintf("/www/sites/%s/proxy/*.conf", website.Alias)
if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil { if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil {
return return
} }
@ -1248,7 +1251,9 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e
config *components.Config config *components.Config
) )
for _, configFile := range fileList.Items { for _, configFile := range fileList.Items {
proxyConfig := request.WebsiteProxyConfig{} proxyConfig := request.WebsiteProxyConfig{
ID: website.ID,
}
parts := strings.Split(configFile.Name, ".") parts := strings.Split(configFile.Name, ".")
proxyConfig.Name = parts[0] proxyConfig.Name = parts[0]
if parts[1] == "conf" { if parts[1] == "conf" {
@ -1271,8 +1276,13 @@ func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, e
} }
proxyConfig.ProxyPass = location.ProxyPass proxyConfig.ProxyPass = location.ProxyPass
proxyConfig.Cache = location.Cache proxyConfig.Cache = location.Cache
//proxyConfig.CacheTime = location.CacheTime if location.CacheTime > 0 {
proxyConfig.CacheTime = location.CacheTime
proxyConfig.CacheUnit = location.CacheUint
}
proxyConfig.Match = location.Match proxyConfig.Match = location.Match
proxyConfig.Modifier = location.Modifier
proxyConfig.ProxyHost = location.Host
res = append(res, proxyConfig) res = append(res, proxyConfig)
} }
return return

View File

@ -1,13 +1,18 @@
package components package components
import (
"regexp"
"strconv"
)
type Location struct { type Location struct {
Modifier string Modifier string
Match string Match string
Cache bool Cache bool
ProxyPass string ProxyPass string
Host string Host string
CacheTime string CacheTime int
CacheUint string
Comment string Comment string
Directives []IDirective Directives []IDirective
Line int Line int
@ -40,7 +45,18 @@ func NewLocation(directive IDirective) *Location {
dirs := dir.GetBlock().GetDirectives() dirs := dir.GetBlock().GetDirectives()
for _, di := range dirs { for _, di := range dirs {
if di.GetName() == "expires" { if di.GetName() == "expires" {
location.CacheTime = di.GetParameters()[0] re := regexp.MustCompile(`^(\d+)(\w+)$`)
matches := re.FindStringSubmatch(di.GetParameters()[0])
if matches == nil {
continue
}
cacheTime, err := strconv.Atoi(matches[1])
if err != nil {
continue
}
unit := matches[2]
location.CacheUint = unit
location.CacheTime = cacheTime
} }
} }
} }
@ -158,7 +174,7 @@ func (l *Location) ChangePath(Modifier string, Match string) {
l.Match = Match l.Match = Match
} }
func (l *Location) AddCache(cacheTime string) { func (l *Location) AddCache(cacheTime int, cacheUint string) {
l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"}) l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"})
directives := l.GetDirectives() directives := l.GetDirectives()
newDir := &Directive{ newDir := &Directive{
@ -169,7 +185,7 @@ func (l *Location) AddCache(cacheTime string) {
block := &Block{} block := &Block{}
block.Directives = append(block.Directives, &Directive{ block.Directives = append(block.Directives, &Directive{
Name: "expires", Name: "expires",
Parameters: []string{cacheTime}, Parameters: []string{strconv.Itoa(cacheTime) + cacheUint},
}) })
newDir.Block = block newDir.Block = block
directives = append(directives, newDir) directives = append(directives, newDir)
@ -180,6 +196,7 @@ func (l *Location) AddCache(cacheTime string) {
l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", "10m"}) l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", "10m"})
l.Cache = true l.Cache = true
l.CacheTime = cacheTime l.CacheTime = cacheTime
l.CacheUint = cacheUint
} }
func (l *Location) RemoveCache() { func (l *Location) RemoveCache() {
@ -191,6 +208,7 @@ func (l *Location) RemoveCache() {
l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"}) l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"})
l.CacheTime = "" l.CacheTime = 0
l.CacheUint = ""
l.Cache = false l.Cache = false
} }

View File

@ -423,9 +423,6 @@ const message = {
remoteConn: 'External connection address', remoteConn: 'External connection address',
remoteConnHelper2: 'Use this address for non-container or external connections', remoteConnHelper2: 'Use this address for non-container or external connections',
localIP: 'Local IP', localIP: 'Local IP',
userGroup: 'User/Group',
user: 'User',
uGroup: 'Group',
}, },
container: { container: {
createContainer: 'Create container', createContainer: 'Create container',
@ -1181,6 +1178,21 @@ const message = {
'Some programs need to specify a secondary directory as the running directory, such as ThinkPHP5, Laravel', 'Some programs need to specify a secondary directory as the running directory, such as ThinkPHP5, Laravel',
runUserHelper: runUserHelper:
'For websites deployed through the PHP runtime environment, all files, folder owners, and user groups under the index and subdirectories need to be set to 1000, command: chown -R 1000:1000 index', 'For websites deployed through the PHP runtime environment, all files, folder owners, and user groups under the index and subdirectories need to be set to 1000, command: chown -R 1000:1000 index',
userGroup: 'User/Group',
user: 'User',
uGroup: 'Group',
proxyPath: 'Proxy Path',
proxyPass: 'Target URL',
cache: 'Cache',
status: 'Status',
createProxy: 'Create reverse proxy',
editProxy: 'Edit reverse proxy',
cacheTime: 'Cache time',
enableCache: 'Open cache',
proxyHost: 'Send domain name',
disabled: 'Stopped',
startProxy: 'Start Reverse proxy',
stopProxy: 'Stop the Reverse proxy',
}, },
php: { php: {
short_open_tag: 'Short tag support', short_open_tag: 'Short tag support',

View File

@ -1183,7 +1183,6 @@ const message = {
userGroup: '运行用户/', userGroup: '运行用户/',
user: '用户', user: '用户',
uGroup: '用户组', uGroup: '用户组',
addProxy: '添加反向代理',
proxyPath: '代理目录', proxyPath: '代理目录',
proxyPass: '目标URL', proxyPass: '目标URL',
cache: '缓存', cache: '缓存',
@ -1194,6 +1193,8 @@ const message = {
enableCache: '开启缓存', enableCache: '开启缓存',
proxyHost: '发送域名', proxyHost: '发送域名',
disabled: '已停止', disabled: '已停止',
startProxy: '开启反向代理',
stopProxy: '关闭反向代理',
}, },
php: { php: {
short_open_tag: '短标签支持', short_open_tag: '短标签支持',

View File

@ -1,24 +1,24 @@
<template> <template>
<el-drawer v-model="open" :close-on-click-modal="false" size="40%" :before-close="handleClose"> <el-drawer v-model="open" :close-on-click-modal="false" size="40%" :before-close="handleClose">
<template #header> <template #header>
<DrawerHeader :header="$t('website.createProxy')" :back="handleClose" /> <DrawerHeader :header="$t('website.' + proxy.operate + 'Proxy')" :back="handleClose" />
</template> </template>
<el-row v-loading="loading"> <el-row v-loading="loading">
<el-col :span="22" :offset="1"> <el-col :span="22" :offset="1">
<el-form ref="proxyForm" label-position="top" :model="proxy" :rules="rules"> <el-form ref="proxyForm" label-position="top" :model="proxy" :rules="rules">
<el-form-item :label="$t('commons.table.name')" prop="name"> <el-form-item :label="$t('commons.table.name')" prop="name">
<el-input v-model.trim="proxy.name"></el-input> <el-input v-model.trim="proxy.name" :disabled="proxy.operate === 'edit'"></el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('website.proxyPath')" prop="match"> <el-form-item :label="$t('website.proxyPath')" prop="match">
<el-input v-model.trim="proxy.match"></el-input> <el-input v-model.trim="proxy.match"></el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('website.enableCache')" prop="cache"> <el-form-item :label="$t('website.enableCache')" prop="cache">
<el-switch v-model="proxy.cache"></el-switch> <el-switch v-model="proxy.cache" @change="changeCache(proxy.cache)"></el-switch>
</el-form-item> </el-form-item>
<el-form-item :label="$t('website.cacheTime')" prop="cacheTime" v-if="proxy.cache"> <el-form-item :label="$t('website.cacheTime')" prop="cacheTime" v-if="proxy.cache">
<el-input v-model.number="proxy.cacheTime" maxlength="15"> <el-input v-model.number="proxy.cacheTime" maxlength="15">
<template #append> <template #append>
<el-select v-model="proxy.cacheUnit" style="width: 80px"> <el-select v-model="proxy.cacheUnit" style="width: 100px">
<el-option <el-option
v-for="(unit, index) in Units" v-for="(unit, index) in Units"
:key="index" :key="index"
@ -65,7 +65,6 @@ import { ref } from 'vue';
import { MsgSuccess } from '@/utils/message'; import { MsgSuccess } from '@/utils/message';
import { Website } from '@/api/interface/website'; import { Website } from '@/api/interface/website';
import { Units } from '@/global/mimetype'; import { Units } from '@/global/mimetype';
// import { Website } from '@/api/interface/website';
const proxyForm = ref<FormInstance>(); const proxyForm = ref<FormInstance>();
const rules = ref({ const rules = ref({
@ -103,9 +102,20 @@ const handleClose = () => {
const acceptParams = async (proxyParam: Website.ProxyConfig) => { const acceptParams = async (proxyParam: Website.ProxyConfig) => {
proxy.value = proxyParam; proxy.value = proxyParam;
console.log(proxy.value);
open.value = true; open.value = true;
}; };
const changeCache = (cache: boolean) => {
if (cache) {
proxy.value.cacheTime = 1;
proxy.value.cacheUnit = 'm';
} else {
proxy.value.cacheTime = 0;
proxy.value.cacheUnit = '';
}
};
const submit = async (formEl: FormInstance | undefined) => { const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return; if (!formEl) return;
await formEl.validate((valid) => { await formEl.validate((valid) => {
@ -115,7 +125,11 @@ const submit = async (formEl: FormInstance | undefined) => {
loading.value = true; loading.value = true;
CreateProxyConfig(proxy.value) CreateProxyConfig(proxy.value)
.then(() => { .then(() => {
if (proxy.value.operate == 'create') {
MsgSuccess(i18n.global.t('commons.msg.createSuccess')); MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
} else {
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
}
handleClose(); handleClose();
}) })
.finally(() => { .finally(() => {

View File

@ -1,36 +1,46 @@
<template> <template>
<ComplexTable :data="data" @search="search" v-loading="loading"> <ComplexTable :data="data" @search="search" v-loading="loading">
<template #toolbar> <template #toolbar>
<el-button type="primary" plain @click="openCreate">{{ $t('website.addProxy') }}</el-button> <el-button type="primary" plain @click="openCreate">{{ $t('website.createProxy') }}</el-button>
</template> </template>
<el-table-column :label="$t('commons.table.name')" prop="name"></el-table-column> <el-table-column :label="$t('commons.table.name')" prop="name"></el-table-column>
<el-table-column :label="$t('website.proxyPath')" prop="match"></el-table-column> <el-table-column :label="$t('website.proxyPath')" prop="match"></el-table-column>
<el-table-column :label="$t('website.proxyPass')" prop="proxyPass"></el-table-column> <el-table-column :label="$t('website.proxyPass')" prop="proxyPass"></el-table-column>
<el-table-column :label="$t('website.cache')" prop="cache"> <el-table-column :label="$t('website.cache')" prop="cache">
<template #default="{ row }"> <template #default="{ row }">
<el-switch v-model="row.cache"></el-switch> <el-switch v-model="row.cache" @change="changeCache(row)"></el-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.table.status')" prop="enable"> <el-table-column :label="$t('commons.table.status')" prop="enable">
<template #default="{ row }"> <template #default="{ row }">
<el-button v-if="row.enable" link type="success" :icon="VideoPlay"> <el-button v-if="row.enable" link type="success" :icon="VideoPlay" @click="opProxy(row)">
{{ $t('commons.status.running') }} {{ $t('commons.status.running') }}
</el-button> </el-button>
<el-button v-else link type="danger" :icon="VideoPause"> <el-button v-else link type="danger" :icon="VideoPause" @click="opProxy(row)">
{{ $t('commons.status.stopped') }} {{ $t('commons.status.stopped') }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
<fu-table-operations
:ellipsis="10"
width="260px"
:buttons="buttons"
:label="$t('commons.table.operate')"
fixed="right"
fix
/>
</ComplexTable> </ComplexTable>
<Create ref="createRef" @close="search()" /> <Create ref="createRef" @close="search()" />
</template> </template>
<script lang="ts" setup name="proxy"> <script lang="ts" setup name="proxy">
import { Website } from '@/api/interface/website'; import { Website } from '@/api/interface/website';
import { GetProxyConfig } from '@/api/modules/website'; import { CreateProxyConfig, GetProxyConfig } from '@/api/modules/website';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import Create from './create/index.vue'; import Create from './create/index.vue';
import { VideoPlay, VideoPause } from '@element-plus/icons-vue'; import { VideoPlay, VideoPause } from '@element-plus/icons-vue';
import i18n from '@/lang';
import { MsgSuccess } from '@/utils/message';
const props = defineProps({ const props = defineProps({
id: { id: {
@ -45,6 +55,15 @@ const loading = ref(false);
const data = ref(); const data = ref();
const createRef = ref(); const createRef = ref();
const buttons = [
{
label: i18n.global.t('commons.button.edit'),
click: function (row: Website.ProxyConfig) {
openEdit(row);
},
},
];
const initData = (id: number): Website.ProxyConfig => ({ const initData = (id: number): Website.ProxyConfig => ({
id: id, id: id,
operate: 'create', operate: 'create',
@ -62,6 +81,56 @@ const initData = (id: number): Website.ProxyConfig => ({
const openCreate = () => { const openCreate = () => {
createRef.value.acceptParams(initData(id.value)); createRef.value.acceptParams(initData(id.value));
}; };
const openEdit = (proxyConfig: Website.ProxyConfig) => {
let proxy = JSON.parse(JSON.stringify(proxyConfig));
proxy.operate = 'edit';
createRef.value.acceptParams(proxy);
};
const changeCache = (proxyConfig: Website.ProxyConfig) => {
proxyConfig.operate = 'edit';
if (proxyConfig.cache) {
proxyConfig.cacheTime = 1;
proxyConfig.cacheUnit = 'm';
}
submit(proxyConfig);
};
const submit = async (proxyConfig: Website.ProxyConfig) => {
loading.value = true;
CreateProxyConfig(proxyConfig)
.then(() => {
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
search();
})
.finally(() => {
loading.value = false;
});
};
const opProxy = (proxyConfig: Website.ProxyConfig) => {
let proxy = JSON.parse(JSON.stringify(proxyConfig));
proxy.enable = !proxyConfig.enable;
let message = '';
if (proxy.enable) {
proxy.operate = 'enable';
message = i18n.global.t('website.startProxy');
} else {
proxy.operate = 'disable';
message = i18n.global.t('website.stopProxy');
}
ElMessageBox.confirm(message, i18n.global.t('cronjob.changeStatus'), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
})
.then(async () => {
await submit(proxy);
search();
})
.catch(() => {});
};
const search = async () => { const search = async () => {
try { try {
loading.value = true; loading.value = true;

View File

@ -39,7 +39,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
host: '0.0.0.0', host: '0.0.0.0',
proxy: { proxy: {
'/api/v1': { '/api/v1': {
target: 'http://localhost:9999/', target: 'http://192.168.1.15:9999/',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
}, },