mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-02-08 01:20:07 +08:00
feat: 增加流量限制功能
This commit is contained in:
parent
daa2e12420
commit
d5aee147f4
@ -10,17 +10,41 @@ type NginxConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type NginxConfigReq struct {
|
type NginxConfigReq struct {
|
||||||
Scope NginxScope `json:"scope"`
|
Scope NginxScope `json:"scope"`
|
||||||
WebSiteID uint `json:"webSiteId" validate:"required"`
|
Operate NginxOp `json:"operate"`
|
||||||
Params map[string]string `json:"params"`
|
WebSiteID uint `json:"webSiteId" validate:"required"`
|
||||||
|
Params interface{} `json:"params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NginxScope string
|
type NginxScope string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Index NginxScope = "index"
|
Index NginxScope = "index"
|
||||||
|
LimitConn NginxScope = "limit-conn"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NginxOp string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ConfigNew NginxOp = "add"
|
||||||
|
ConfigUpdate NginxOp = "update"
|
||||||
|
ConfigDel NginxOp = "delete"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ScopeKeyMap = map[NginxScope][]string{
|
var ScopeKeyMap = map[NginxScope][]string{
|
||||||
Index: {"index"},
|
Index: {"index"},
|
||||||
|
LimitConn: {"limit_conn", "limit_rate", "limit_conn_zone"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var RepeatKeys = map[string]struct {
|
||||||
|
}{
|
||||||
|
"limit_conn": {},
|
||||||
|
"limit_conn_zone": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
type NginxParam struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
SecondKey string `json:"secondKey"`
|
||||||
|
IsRepeatKey bool `json:"isRepeatKey"`
|
||||||
|
Params []string `json:"params"`
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func (w WebsiteService) DeleteWebsiteDomain(domainId uint) error {
|
|||||||
return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId))
|
return websiteDomainRepo.DeleteBy(context.TODO(), commonRepo.WithByID(domainId))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w WebsiteService) GetNginxConfigByScope(req dto.NginxConfigReq) (map[string]interface{}, error) {
|
func (w WebsiteService) GetNginxConfigByScope(req dto.NginxConfigReq) ([]dto.NginxParam, error) {
|
||||||
|
|
||||||
keys, ok := dto.ScopeKeyMap[req.Scope]
|
keys, ok := dto.ScopeKeyMap[req.Scope]
|
||||||
if !ok || len(keys) == 0 {
|
if !ok || len(keys) == 0 {
|
||||||
@ -207,19 +207,13 @@ func (w WebsiteService) UpdateNginxConfigByScope(req dto.NginxConfigReq) error {
|
|||||||
if !ok || len(keys) == 0 {
|
if !ok || len(keys) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
keyValues := make(map[string][]string, len(keys))
|
|
||||||
for k, v := range req.Params {
|
|
||||||
for _, name := range keys {
|
|
||||||
if name == k {
|
|
||||||
keyValues[k] = getNginxParams(k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebSiteID))
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(req.WebSiteID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if req.Operate == dto.ConfigDel {
|
||||||
|
return deleteNginxConfig(website, keys, req.Scope)
|
||||||
|
}
|
||||||
|
|
||||||
return updateNginxConfig(website, keyValues)
|
return updateNginxConfig(website, getNginxParams(req.Params, keys), req.Scope)
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,8 @@ func opNginx(containerName, operate string) error {
|
|||||||
if operate == "check" {
|
if operate == "check" {
|
||||||
nginxCmd = fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -t")
|
nginxCmd = fmt.Sprintf("docker exec -i %s %s", containerName, "nginx -t")
|
||||||
}
|
}
|
||||||
if _, err := cmd.Exec(nginxCmd); err != nil {
|
if out, err := cmd.Exec(nginxCmd); err != nil {
|
||||||
return err
|
return errors.New(out)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -206,36 +206,50 @@ func deleteListenAndServerName(website model.WebSite, ports []int, domains []str
|
|||||||
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNginxConfigByKeys(website model.WebSite, keys []string) (map[string]interface{}, error) {
|
func getNginxConfigByKeys(website model.WebSite, keys []string) ([]dto.NginxParam, error) {
|
||||||
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
config := nginxConfig.Config
|
config := nginxConfig.Config
|
||||||
server := config.FindServers()[0]
|
server := config.FindServers()[0]
|
||||||
res := make(map[string]interface{})
|
|
||||||
|
var res []dto.NginxParam
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
dirs := server.FindDirectives(key)
|
dirs := server.FindDirectives(key)
|
||||||
for _, dir := range dirs {
|
for _, dir := range dirs {
|
||||||
res[dir.GetName()] = dir.GetParameters()
|
nginxParam := dto.NginxParam{
|
||||||
|
Name: dir.GetName(),
|
||||||
|
Params: dir.GetParameters(),
|
||||||
|
}
|
||||||
|
if isRepeatKey(key) {
|
||||||
|
nginxParam.IsRepeatKey = true
|
||||||
|
nginxParam.SecondKey = dir.GetParameters()[0]
|
||||||
|
}
|
||||||
|
res = append(res, nginxParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNginxConfig(website model.WebSite, keyValues map[string][]string) error {
|
func updateNginxConfig(website model.WebSite, params []dto.NginxParam, scope dto.NginxScope) error {
|
||||||
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
config := nginxConfig.Config
|
config := nginxConfig.Config
|
||||||
|
updateConfig(config, scope)
|
||||||
server := config.FindServers()[0]
|
server := config.FindServers()[0]
|
||||||
for k, v := range keyValues {
|
for _, p := range params {
|
||||||
newDir := components.Directive{
|
newDir := components.Directive{
|
||||||
Name: k,
|
Name: p.Name,
|
||||||
Parameters: v,
|
Parameters: p.Params,
|
||||||
|
}
|
||||||
|
if p.IsRepeatKey {
|
||||||
|
server.UpdateDirectiveBySecondKey(p.Name, p.SecondKey, newDir)
|
||||||
|
} else {
|
||||||
|
server.UpdateDirectives(p.Name, newDir)
|
||||||
}
|
}
|
||||||
server.UpdateDirectives(k, newDir)
|
|
||||||
}
|
}
|
||||||
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -243,13 +257,101 @@ func updateNginxConfig(website model.WebSite, keyValues map[string][]string) err
|
|||||||
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNginxParams(key string, param interface{}) []string {
|
func updateConfig(config *components.Config, scope dto.NginxScope) {
|
||||||
|
if scope == dto.LimitConn {
|
||||||
|
limit := parser.NewStringParser(string(nginx_conf.Limit)).Parse()
|
||||||
|
for _, dir := range limit.GetDirectives() {
|
||||||
|
newDir := components.Directive{
|
||||||
|
Name: dir.GetName(),
|
||||||
|
Parameters: dir.GetParameters(),
|
||||||
|
}
|
||||||
|
config.UpdateDirectiveBySecondKey(dir.GetName(), dir.GetParameters()[0], newDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteNginxConfig(website model.WebSite, keys []string, scope dto.NginxScope) error {
|
||||||
|
nginxConfig, err := getNginxConfig(website.PrimaryDomain)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
config := nginxConfig.Config
|
||||||
|
config.RemoveDirectives(keys)
|
||||||
|
server := config.FindServers()[0]
|
||||||
|
server.RemoveDirectives(keys)
|
||||||
|
if err := nginx.WriteConfig(config, nginx.IndentedStyle); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nginxCheckAndReload(nginxConfig.OldContent, nginxConfig.FilePath, nginxConfig.ContainerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getParamArray(key string, param interface{}) []string {
|
||||||
var res []string
|
var res []string
|
||||||
switch param.(type) {
|
switch param.(type) {
|
||||||
case string:
|
case string:
|
||||||
if key == "index" {
|
if key == "index" {
|
||||||
res = strings.Split(param.(string), "\n")
|
res = strings.Split(param.(string), "\n")
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res = strings.Split(param.(string), " ")
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleParamMap(paramMap map[string]string, keys []string) []dto.NginxParam {
|
||||||
|
var nginxParams []dto.NginxParam
|
||||||
|
for k, v := range paramMap {
|
||||||
|
for _, name := range keys {
|
||||||
|
if name == k {
|
||||||
|
param := dto.NginxParam{
|
||||||
|
Name: k,
|
||||||
|
Params: getParamArray(k, v),
|
||||||
|
}
|
||||||
|
if isRepeatKey(k) {
|
||||||
|
param.IsRepeatKey = true
|
||||||
|
param.SecondKey = param.Params[0]
|
||||||
|
}
|
||||||
|
nginxParams = append(nginxParams, param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nginxParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNginxParams(params interface{}, keys []string) []dto.NginxParam {
|
||||||
|
var nginxParams []dto.NginxParam
|
||||||
|
|
||||||
|
switch params.(type) {
|
||||||
|
case map[string]string:
|
||||||
|
return handleParamMap(params.(map[string]string), keys)
|
||||||
|
case []interface{}:
|
||||||
|
|
||||||
|
if mArray, ok := params.([]interface{}); ok {
|
||||||
|
for _, mA := range mArray {
|
||||||
|
if m, ok := mA.(map[string]interface{}); ok {
|
||||||
|
nginxParams = append(nginxParams, handleParamMap(toMapStr(m), keys)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nginxParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func isRepeatKey(key string) bool {
|
||||||
|
|
||||||
|
if _, ok := dto.RepeatKeys[key]; ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func toMapStr(m map[string]interface{}) map[string]string {
|
||||||
|
ret := make(map[string]string, len(m))
|
||||||
|
for k, v := range m {
|
||||||
|
ret[k] = fmt.Sprint(v)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
@ -1,50 +1,18 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bytes"
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Exec(cmdStr string) (out string, err error) {
|
func Exec(cmdStr string) (string, error) {
|
||||||
command := exec.CommandContext(context.Background(), "bash", "-c", cmdStr)
|
cmd := exec.Command("bash", "-c", cmdStr)
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
var wg sync.WaitGroup
|
cmd.Stdout = &stdout
|
||||||
wg.Add(1)
|
cmd.Stderr = &stderr
|
||||||
|
err := cmd.Run()
|
||||||
stdout, err := command.StdoutPipe()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return string(stderr.Bytes()), err
|
||||||
}
|
}
|
||||||
readout := bufio.NewReader(stdout)
|
return string(stdout.Bytes()), nil
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
out = getOutput(readout)
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = command.Run()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func getOutput(reader *bufio.Reader) string {
|
|
||||||
var sumOutput string
|
|
||||||
outputBytes := make([]byte, 200)
|
|
||||||
for {
|
|
||||||
n, err := reader.Read(outputBytes)
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
sumOutput += err.Error()
|
|
||||||
}
|
|
||||||
output := string(outputBytes[:n])
|
|
||||||
sumOutput += output
|
|
||||||
}
|
|
||||||
return sumOutput
|
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@ func (b *Block) FindDirectives(directiveName string) []IDirective {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) UpdateDirectives(directiveName string, directive Directive) {
|
func (b *Block) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
directives := make([]IDirective, len(b.GetDirectives()))
|
directives := b.GetDirectives()
|
||||||
index := -1
|
index := -1
|
||||||
for i, dir := range b.GetDirectives() {
|
for i, dir := range directives {
|
||||||
if dir.GetName() == directiveName {
|
if dir.GetName() == directiveName {
|
||||||
index = i
|
index = i
|
||||||
break
|
break
|
||||||
@ -44,6 +44,25 @@ func (b *Block) UpdateDirectives(directiveName string, directive Directive) {
|
|||||||
b.Directives = directives
|
b.Directives = directives
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Block) UpdateDirectiveBySecondKey(name string, key string, directive Directive) {
|
||||||
|
|
||||||
|
directives := b.GetDirectives()
|
||||||
|
|
||||||
|
index := -1
|
||||||
|
for i, dir := range directives {
|
||||||
|
if dir.GetName() == name && dir.GetParameters()[0] == key {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > -1 {
|
||||||
|
directives[index] = &directive
|
||||||
|
} else {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
}
|
||||||
|
b.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
func (b *Block) AddDirectives(directive Directive) {
|
func (b *Block) AddDirectives(directive Directive) {
|
||||||
directives := append(b.GetDirectives(), &directive)
|
directives := append(b.GetDirectives(), &directive)
|
||||||
b.Directives = directives
|
b.Directives = directives
|
||||||
|
@ -144,11 +144,28 @@ func (s *Server) UpdateRootProxy(proxy []string) {
|
|||||||
Parameters: proxy,
|
Parameters: proxy,
|
||||||
})
|
})
|
||||||
newDir.Block = block
|
newDir.Block = block
|
||||||
s.UpdateDirectives("location", newDir)
|
s.UpdateDirectiveBySecondKey("location", "/", newDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) UpdateDirectiveBySecondKey(name string, key string, directive Directive) {
|
||||||
|
directives := s.Directives
|
||||||
|
index := -1
|
||||||
|
for i, dir := range directives {
|
||||||
|
if dir.GetName() == name && dir.GetParameters()[0] == key {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if index > -1 {
|
||||||
|
directives[index] = &directive
|
||||||
|
} else {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
}
|
||||||
|
s.Directives = directives
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveListenByBind(bind string) {
|
func (s *Server) RemoveListenByBind(bind string) {
|
||||||
index := 0
|
index := 0
|
||||||
listens := s.Listens
|
listens := s.Listens
|
||||||
@ -176,14 +193,19 @@ func (s *Server) FindDirectives(directiveName string) []IDirective {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) UpdateDirectives(directiveName string, directive Directive) {
|
func (s *Server) UpdateDirectives(directiveName string, directive Directive) {
|
||||||
directives := make([]IDirective, 0)
|
directives := s.Directives
|
||||||
for _, dir := range s.Directives {
|
index := -1
|
||||||
|
for i, dir := range directives {
|
||||||
if dir.GetName() == directiveName {
|
if dir.GetName() == directiveName {
|
||||||
directives = append(directives, &directive)
|
index = i
|
||||||
} else {
|
break
|
||||||
directives = append(directives, dir)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if index > -1 {
|
||||||
|
directives[index] = &directive
|
||||||
|
} else {
|
||||||
|
directives = append(directives, &directive)
|
||||||
|
}
|
||||||
s.Directives = directives
|
s.Directives = directives
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +219,7 @@ func (s *Server) RemoveDirectives(names []string) {
|
|||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
nameMaps[name] = struct{}{}
|
nameMaps[name] = struct{}{}
|
||||||
}
|
}
|
||||||
directives := s.GetDirectives()
|
directives := s.Directives
|
||||||
var newDirectives []IDirective
|
var newDirectives []IDirective
|
||||||
for _, dir := range directives {
|
for _, dir := range directives {
|
||||||
if _, ok := nameMaps[dir.GetName()]; ok {
|
if _, ok := nameMaps[dir.GetName()]; ok {
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
limit_conn perserver 300;
|
limit_conn_zone $binary_remote_addr zone=perip:10m;
|
||||||
limit_conn perip 25;
|
limit_conn_zone $server_name zone=perserver:10m;
|
||||||
limit_rate 512k;
|
|
@ -12,3 +12,6 @@ var HTTPS []byte
|
|||||||
|
|
||||||
//go:embed website_default.conf
|
//go:embed website_default.conf
|
||||||
var WebsiteDefault []byte
|
var WebsiteDefault []byte
|
||||||
|
|
||||||
|
//go:embed limit.conf
|
||||||
|
var Limit []byte
|
||||||
|
@ -65,8 +65,16 @@ export namespace WebSite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface NginxConfigReq {
|
export interface NginxConfigReq {
|
||||||
|
operate: string;
|
||||||
websiteId: number;
|
websiteId: number;
|
||||||
scope: string;
|
scope: string;
|
||||||
params?: any;
|
params?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NginxParam {
|
||||||
|
name: string;
|
||||||
|
secondKey: string;
|
||||||
|
isRepeatKey: string;
|
||||||
|
params: string[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ export const CreateDomain = (req: WebSite.DomainCreate) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const GetNginxConfig = (req: WebSite.NginxConfigReq) => {
|
export const GetNginxConfig = (req: WebSite.NginxConfigReq) => {
|
||||||
return http.post<any>(`/websites/config`, req);
|
return http.post<WebSite.NginxParam[]>(`/websites/config`, req);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UpdateNginxConfig = (req: WebSite.NginxConfigReq) => {
|
export const UpdateNginxConfig = (req: WebSite.NginxConfigReq) => {
|
||||||
|
@ -687,5 +687,12 @@ export default {
|
|||||||
addDomain: '新增域名',
|
addDomain: '新增域名',
|
||||||
domainConfig: '域名设置',
|
domainConfig: '域名设置',
|
||||||
defaultDoc: '默认文档',
|
defaultDoc: '默认文档',
|
||||||
|
perserver: '并发限制',
|
||||||
|
perserverHelper: '限制当前站点最大并发数',
|
||||||
|
perip: '单IP限制',
|
||||||
|
peripHelper: '限制单个IP访问最大并发数',
|
||||||
|
rate: '流量限制',
|
||||||
|
rateHelper: '限制每个请求的流量上限(单位:KB)',
|
||||||
|
limtHelper: '启用流量控制',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,23 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<el-row :gutter="20">
|
||||||
<el-form ref="defaultForm" label-position="top" :model="defaultModel" :rules="rules" :loading="loading">
|
<el-col :span="8" :offset="2">
|
||||||
<el-form-item :label="$t('website.domain')" prop="index">
|
<el-form ref="defaultForm" label-position="top" :model="defaultModel" :rules="rules" :loading="loading">
|
||||||
<el-col :span="8">
|
<el-form-item :label="$t('website.defaultDoc')" prop="index">
|
||||||
<el-input
|
<el-input
|
||||||
width="40%"
|
|
||||||
v-model="defaultModel.index"
|
v-model="defaultModel.index"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:autosize="{ minRows: 8, maxRows: 20 }"
|
:autosize="{ minRows: 8, maxRows: 20 }"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-col>
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-form>
|
||||||
</el-form>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="submit(defaultForm)" :loading="loading">
|
<el-button type="primary" @click="submit(defaultForm)" :loading="loading">
|
||||||
{{ $t('commons.button.save') }}
|
{{ $t('commons.button.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</el-col>
|
||||||
</div>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@ -45,6 +42,7 @@ let defaultModel = ref({
|
|||||||
index: '',
|
index: '',
|
||||||
});
|
});
|
||||||
let req = ref({
|
let req = ref({
|
||||||
|
operate: 'update',
|
||||||
scope: 'index',
|
scope: 'index',
|
||||||
websiteId: websiteId.value,
|
websiteId: websiteId.value,
|
||||||
params: {},
|
params: {},
|
||||||
@ -75,13 +73,14 @@ const search = (req: WebSite.NginxConfigReq) => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
GetNginxConfig(req)
|
GetNginxConfig(req)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const params = res.data['index'];
|
if (res.data.length > 0) {
|
||||||
let values = '';
|
const indexParam = res.data[0];
|
||||||
for (const param of params) {
|
let values = '';
|
||||||
values = values + param + '\n';
|
for (const param of indexParam.params) {
|
||||||
|
values = values + param + '\n';
|
||||||
|
}
|
||||||
|
defaultModel.value.index = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultModel.value.index = values;
|
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
<el-tab-pane :label="$t('website.defaultDoc')">
|
<el-tab-pane :label="$t('website.defaultDoc')">
|
||||||
<Default :id="id" v-if="index == '1'"></Default>
|
<Default :id="id" v-if="index == '1'"></Default>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('website.rate')">
|
||||||
|
<LimitConn :id="id" v-if="index == '2'"></LimitConn>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="HTTPS">Role</el-tab-pane>
|
<el-tab-pane label="HTTPS">Role</el-tab-pane>
|
||||||
<el-tab-pane label="域名跳转">Task</el-tab-pane>
|
<el-tab-pane label="域名跳转">Task</el-tab-pane>
|
||||||
<el-tab-pane label="错误页面">Task</el-tab-pane>
|
<el-tab-pane label="错误页面">Task</el-tab-pane>
|
||||||
<el-tab-pane label="过期时间">Task</el-tab-pane>
|
<el-tab-pane label="过期时间">Task</el-tab-pane>
|
||||||
<el-tab-pane label="流量限制">Task</el-tab-pane>
|
|
||||||
<el-tab-pane label="默认文档">Task</el-tab-pane>
|
<el-tab-pane label="默认文档">Task</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
@ -20,6 +23,7 @@ import { computed, ref } from 'vue';
|
|||||||
|
|
||||||
import Doamin from './domain/index.vue';
|
import Doamin from './domain/index.vue';
|
||||||
import Default from './default-doc/index.vue';
|
import Default from './default-doc/index.vue';
|
||||||
|
import LimitConn from './limit-conn/index.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="8" :offset="2">
|
||||||
|
<el-checkbox v-model="enable" @change="changeEnable">{{ $t('website.limtHelper') }}</el-checkbox>
|
||||||
|
<el-form ref="limitForm" label-position="left" :model="form" :rules="rules" :loading="loading">
|
||||||
|
<el-form-item :label="$t('website.perserver')" prop="perserver">
|
||||||
|
<el-input v-model="form.perserver"></el-input>
|
||||||
|
<span class="input-help">{{ $t('website.perserverHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.perip')" prop="perip">
|
||||||
|
<el-input v-model="form.perip"></el-input>
|
||||||
|
<span class="input-help">{{ $t('website.peripHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('website.rate')" prop="rate">
|
||||||
|
<el-input v-model="form.rate"></el-input>
|
||||||
|
<span class="input-help">{{ $t('website.rateHelper') }}</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-button type="primary" @click="submit(limitForm)" :loading="loading">
|
||||||
|
{{ $t('commons.button.save') }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Rules } from '@/global/form-rules';
|
||||||
|
import { WebSite } from '@/api/interface/website';
|
||||||
|
import { GetNginxConfig, UpdateNginxConfig } from '@/api/modules/website';
|
||||||
|
import { ElMessage, FormInstance } from 'element-plus';
|
||||||
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
|
import i18n from '@/lang';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const websiteId = computed(() => {
|
||||||
|
return Number(props.id);
|
||||||
|
});
|
||||||
|
let rules = ref({
|
||||||
|
perserver: [Rules.requiredInput],
|
||||||
|
perip: [Rules.requiredInput],
|
||||||
|
rate: [Rules.requiredInput],
|
||||||
|
});
|
||||||
|
const limitForm = ref<FormInstance>();
|
||||||
|
let form = reactive({
|
||||||
|
perserver: 300,
|
||||||
|
perip: 25,
|
||||||
|
rate: 512,
|
||||||
|
});
|
||||||
|
let req = reactive({
|
||||||
|
operate: 'update',
|
||||||
|
scope: 'limit-conn',
|
||||||
|
websiteId: websiteId.value,
|
||||||
|
params: [{}],
|
||||||
|
});
|
||||||
|
let enable = ref(false);
|
||||||
|
let loading = ref(false);
|
||||||
|
|
||||||
|
const search = (req: WebSite.NginxConfigReq) => {
|
||||||
|
loading.value = true;
|
||||||
|
GetNginxConfig(req)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
enable.value = true;
|
||||||
|
for (const param of res.data) {
|
||||||
|
if (param.name === 'limit_conn') {
|
||||||
|
if (param.secondKey === 'perserver') {
|
||||||
|
form.perserver = Number(param.params[1]);
|
||||||
|
}
|
||||||
|
if (param.secondKey === 'perip') {
|
||||||
|
form.perip = Number(param.params[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (param.name === 'limit_rate') {
|
||||||
|
console.log(param.params[0].match(/\d+/g)?.join(''));
|
||||||
|
form.rate = Number(param.params[0].match(/\d+/g));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enable.value = false;
|
||||||
|
req.operate = 'add';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = async (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
await formEl.validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
let params = [
|
||||||
|
{
|
||||||
|
limit_conn: 'perserver ' + String(form.perserver),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
limit_conn: 'perip ' + String(form.perip),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
limit_rate: String(form.rate) + 'k',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
req.params = params;
|
||||||
|
UpdateNginxConfig(req)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success(i18n.global.t('commons.msg.updateSuccess'));
|
||||||
|
search(req);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeEnable = () => {
|
||||||
|
if (!enable.value) {
|
||||||
|
req.operate = 'delete';
|
||||||
|
} else {
|
||||||
|
req.operate = 'add';
|
||||||
|
}
|
||||||
|
submit(limitForm.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
search(req);
|
||||||
|
});
|
||||||
|
</script>
|
Loading…
x
Reference in New Issue
Block a user