diff --git a/backend/app/api/v1/website.go b/backend/app/api/v1/website.go index 5c7089523..85f1b11cd 100644 --- a/backend/app/api/v1/website.go +++ b/backend/app/api/v1/website.go @@ -648,3 +648,47 @@ func (b *BaseApi) UpdateSiteDirPermission(c *gin.Context) { } helper.SuccessWithOutData(c) } + +// @Tags Website +// @Summary Get proxy conf +// @Description 获取反向代理配置 +// @Accept json +// @Param request body request.WebsiteProxyReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/proxies [post] +func (b *BaseApi) GetProxyConfig(c *gin.Context) { + var req request.WebsiteProxyReq + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + res, err := websiteService.GetProxies(req.ID) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, res) +} + +// @Tags Website +// @Summary Update proxy conf +// @Description 修改反向代理配置 +// @Accept json +// @Param request body request.WebsiteProxyConfig true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /websites/proxies/update [post] +func (b *BaseApi) UpdateProxyConfig(c *gin.Context) { + var req request.WebsiteProxyConfig + if err := c.ShouldBindJSON(&req); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) + return + } + err := websiteService.OperateProxy(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/dto/nginx.go b/backend/app/dto/nginx.go index dcfcffd62..074b8add2 100644 --- a/backend/app/dto/nginx.go +++ b/backend/app/dto/nginx.go @@ -31,10 +31,12 @@ type NginxParam struct { type NginxKey string const ( - Index NginxKey = "index" - LimitConn NginxKey = "limit-conn" - SSL NginxKey = "ssl" - HttpPer NginxKey = "http-per" + Index NginxKey = "index" + LimitConn NginxKey = "limit-conn" + SSL NginxKey = "ssl" + CACHE NginxKey = "cache" + HttpPer NginxKey = "http-per" + ProxyCache NginxKey = "proxy-cache" ) var ScopeKeyMap = map[NginxKey][]string{ @@ -46,5 +48,7 @@ var ScopeKeyMap = map[NginxKey][]string{ var StaticFileKeyMap = map[NginxKey]struct { }{ - SSL: {}, + SSL: {}, + CACHE: {}, + ProxyCache: {}, } diff --git a/backend/app/dto/request/website.go b/backend/app/dto/request/website.go index 9e7b4f4a1..af0dc6e57 100644 --- a/backend/app/dto/request/website.go +++ b/backend/app/dto/request/website.go @@ -156,3 +156,23 @@ type WebsiteUpdateDirPermission struct { User string `json:"user" validate:"required"` Group string `json:"group" validate:"required"` } + +type WebsiteProxyConfig struct { + ID uint `json:"id" validate:"required"` + Operate string `json:"operate" validate:"required"` + Enable bool `json:"enable" validate:"required"` + Cache bool `json:"cache" validate:"required"` + CacheTime int `json:"cacheTime" validate:"required"` + CacheUnit string `json:"cacheUnit" validate:"required"` + Name string `json:"name" validate:"required"` + Modifier string `json:"modifier" validate:"required"` + Match string `json:"match" validate:"required"` + ProxyPass string `json:"proxyPass" validate:"required"` + ProxyHost string `json:"proxyHost" validate:"required"` + FilePath string `json:"filePath"` + Replaces []map[string]string `json:"replaces"` +} + +type WebsiteProxyReq struct { + ID uint `json:"id" validate:"required"` +} diff --git a/backend/app/service/nginx_utils.go b/backend/app/service/nginx_utils.go index 9eb87d466..1478ef660 100644 --- a/backend/app/service/nginx_utils.go +++ b/backend/app/service/nginx_utils.go @@ -161,6 +161,10 @@ func getNginxParamsFromStaticFile(scope dto.NginxKey, newParams []dto.NginxParam switch scope { case dto.SSL: newConfig = parser.NewStringParser(string(nginx_conf.SSL)).Parse() + case dto.CACHE: + newConfig = parser.NewStringParser(string(nginx_conf.Cache)).Parse() + case dto.ProxyCache: + newConfig = parser.NewStringParser(string(nginx_conf.ProxyCache)).Parse() } for _, dir := range newConfig.GetDirectives() { addParam := dto.NginxParam{ diff --git a/backend/app/service/website.go b/backend/app/service/website.go index 863247781..3671dd975 100644 --- a/backend/app/service/website.go +++ b/backend/app/service/website.go @@ -10,12 +10,16 @@ import ( "fmt" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/nginx" + "github.com/1Panel-dev/1Panel/backend/utils/nginx/components" + "github.com/1Panel-dev/1Panel/backend/utils/nginx/parser" "github.com/1Panel-dev/1Panel/cmd/server/nginx_conf" "gorm.io/gorm" "os" "path" "reflect" "regexp" + "strconv" "strings" "time" @@ -64,6 +68,8 @@ type IWebsiteService interface { UpdateRewriteConfig(req request.NginxRewriteUpdate) error UpdateSiteDir(req request.WebsiteUpdateDir) error UpdateSitePermission(req request.WebsiteUpdateDirPermission) error + OperateProxy(req request.WebsiteProxyConfig) (err error) + GetProxies(id uint) (res []request.WebsiteProxyConfig, err error) } func NewIWebsiteService() IWebsiteService { @@ -1105,3 +1111,169 @@ func (w WebsiteService) UpdateSitePermission(req request.WebsiteUpdateDirPermiss website.Group = req.Group return websiteRepo.Save(context.Background(), &website) } + +func (w WebsiteService) OperateProxy(req request.WebsiteProxyConfig) (err error) { + var ( + website model.Website + params []response.NginxParam + nginxInstall model.AppInstall + par *parser.Parser + oldContent []byte + ) + + website, err = websiteRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return + } + params, err = getNginxParamsByKeys(constant.NginxScopeHttp, []string{"proxy_cache"}, &website) + if err != nil { + return + } + nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return + } + fileOp := files.NewFileOp() + if len(params) == 0 || len(params[0].Params) == 0 { + commonDir := path.Join(nginxInstall.GetPath(), "www", "common", "proxy") + proxyTempPath := path.Join(commonDir, "proxy_temp_dir") + if !fileOp.Stat(proxyTempPath) { + _ = fileOp.CreateDir(proxyTempPath, 0755) + } + proxyCacheDir := path.Join(commonDir, "proxy_temp_dir") + if !fileOp.Stat(proxyCacheDir) { + _ = fileOp.CreateDir(proxyCacheDir, 0755) + } + nginxParams := getNginxParamsFromStaticFile(dto.CACHE, nil) + if err = updateNginxConfig(constant.NginxScopeHttp, nginxParams, &website); err != nil { + return + } + } + includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy") + if !fileOp.Stat(includeDir) { + _ = fileOp.CreateDir(includeDir, 0755) + } + fileName := fmt.Sprintf("%s.conf", req.Name) + includePath := path.Join(includeDir, fileName) + if !fileOp.Stat(includePath) { + _ = fileOp.CreateFile(includePath) + } + + defer func() { + if err != nil { + switch req.Operate { + case "create": + _ = fileOp.DeleteFile(includePath) + case "update": + _ = fileOp.WriteFile(includePath, bytes.NewReader(oldContent), 0755) + } + } + }() + + var config *components.Config + + switch req.Operate { + case "create": + config = parser.NewStringParser(string(nginx_conf.Proxy)).Parse() + case "update": + par, err = parser.NewParser(includePath) + if err != nil { + return + } + config = par.Parse() + oldContent, err = fileOp.GetContent(includePath) + if err != nil { + return + } + case "delete": + _ = fileOp.DeleteFile(includePath) + return updateNginxConfig(constant.NginxScopeServer, nil, &website) + case "disable": + backName := fmt.Sprintf("%s.bak", req.Name) + backPath := path.Join(includeDir, backName) + _ = fileOp.Rename(includePath, backPath) + return updateNginxConfig(constant.NginxScopeServer, nil, &website) + } + config.FilePath = includePath + directives := config.Directives + location, ok := directives[0].(*components.Location) + if !ok { + err = errors.New("error") + return + } + location.UpdateDirective("proxy_pass", []string{req.ProxyPass}) + location.UpdateDirective("proxy_set_header", []string{"Host", req.ProxyHost}) + location.ChangePath(req.Modifier, req.Match) + if req.Cache { + location.AddCache(strconv.Itoa(req.CacheTime) + req.CacheUnit) + } else { + location.RemoveCache() + } + + if err = nginx.WriteConfig(config, nginx.IndentedStyle); err != nil { + return buserr.WithErr(constant.ErrUpdateBuWebsite, err) + } + nginxInclude := path.Join("www", "sites", website.Alias, "proxy", "*.conf") + if err = updateNginxConfig(constant.NginxScopeServer, []dto.NginxParam{{Name: "include", Params: []string{nginxInclude}}}, &website); err != nil { + return + } + return +} + +func (w WebsiteService) GetProxies(id uint) (res []request.WebsiteProxyConfig, err error) { + var ( + website model.Website + nginxInstall model.AppInstall + fileList response.FileInfo + ) + website, err = websiteRepo.GetFirst(commonRepo.WithByID(id)) + if err != nil { + return + } + nginxInstall, err = getAppInstallByKey(constant.AppOpenresty) + if err != nil { + return + } + includeDir := path.Join(nginxInstall.GetPath(), "www", "sites", website.Alias, "proxy") + fileOp := files.NewFileOp() + if !fileOp.Stat(includeDir) { + return + } + fileList, err = NewIFileService().GetFileList(request.FileOption{FileOption: files.FileOption{Path: includeDir, Expand: true, Page: 1, PageSize: 100}}) + if len(fileList.Items) == 0 { + return + } + var ( + content []byte + config *components.Config + ) + for _, configFile := range fileList.Items { + proxyConfig := request.WebsiteProxyConfig{} + parts := strings.Split(configFile.Name, ".") + proxyConfig.Name = parts[0] + if parts[1] == "conf" { + proxyConfig.Enable = true + } else { + proxyConfig.Enable = false + } + proxyConfig.FilePath = configFile.Path + content, err = fileOp.GetContent(configFile.Path) + if err != nil { + return + } + config = parser.NewStringParser(string(content)).Parse() + directives := config.GetDirectives() + + location, ok := directives[0].(*components.Location) + if !ok { + err = errors.New("error") + return + } + proxyConfig.ProxyPass = location.ProxyPass + proxyConfig.Cache = location.Cache + //proxyConfig.CacheTime = location.CacheTime + proxyConfig.Match = location.Match + res = append(res, proxyConfig) + } + return +} diff --git a/backend/constant/nginx.go b/backend/constant/nginx.go index 996edd307..93b46b868 100644 --- a/backend/constant/nginx.go +++ b/backend/constant/nginx.go @@ -5,8 +5,9 @@ const ( NginxScopeHttp = "http" NginxScopeOut = "out" - NginxReload = "reload" - NginxCheck = "check" + NginxReload = "reload" + NginxCheck = "check" + NginxRestart = "restart" ConfigNew = "add" ConfigUpdate = "update" diff --git a/backend/router/ro_website.go b/backend/router/ro_website.go index 0bdb73f47..987d9ad05 100644 --- a/backend/router/ro_website.go +++ b/backend/router/ro_website.go @@ -51,5 +51,8 @@ func (a *WebsiteRouter) InitWebsiteRouter(Router *gin.RouterGroup) { groupRouter.POST("/dir/update", baseApi.UpdateSiteDir) groupRouter.POST("/dir/permission", baseApi.UpdateSiteDirPermission) + + groupRouter.POST("/proxies", baseApi.GetProxyConfig) + groupRouter.POST("/proxies/update", baseApi.UpdateProxyConfig) } } diff --git a/backend/utils/nginx/components/block.go b/backend/utils/nginx/components/block.go index bbbf5a147..9342156ad 100644 --- a/backend/utils/nginx/components/block.go +++ b/backend/utils/nginx/components/block.go @@ -62,41 +62,6 @@ func (b *Block) UpdateDirective(key string, params []string) { 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) RemoveDirectives(names []string) { -// nameMaps := make(map[string]struct{}, len(names)) -// for _, name := range names { -// nameMaps[name] = struct{}{} -// } -// directives := b.GetDirectives() -// var newDirectives []IDirective -// for _, dir := range directives { -// if _, ok := nameMaps[dir.GetName()]; ok { -// continue -// } -// newDirectives = append(newDirectives, dir) -// } -// b.Directives = newDirectives -//} - func (b *Block) RemoveDirective(key string, params []string) { directives := b.GetDirectives() var newDirectives []IDirective diff --git a/backend/utils/nginx/components/location.go b/backend/utils/nginx/components/location.go index 784ff8c34..894ecaab3 100644 --- a/backend/utils/nginx/components/location.go +++ b/backend/utils/nginx/components/location.go @@ -1,32 +1,196 @@ package components type Location struct { - *Directive - Modifier string - Match string + Modifier string + Match string + Cache bool + ProxyPass string + Host string + CacheTime string + + Comment string + Directives []IDirective + Line int + Parameters []string } -func NewLocation(directive *Directive) *Location { +func NewLocation(directive IDirective) *Location { location := &Location{ - Modifier: "", - Match: "", - Directive: directive, + Modifier: "", + Match: "", + } + directives := make([]IDirective, 0) + if len(directive.GetParameters()) == 0 { + panic("no enough parameter for location") } - if directive.GetBlock() != nil { - directive.Comment = directive.GetBlock().GetComment() + for _, dir := range directive.GetBlock().GetDirectives() { + directives = append(directives, dir) + params := dir.GetParameters() + switch dir.GetName() { + case "proxy_pass": + location.ProxyPass = params[0] + case "proxy_set_header": + if params[0] == "Host" { + location.Host = params[1] + } + case "proxy_cache": + location.Cache = true + case "if": + if params[0] == "(" && params[1] == "$uri" && params[2] == "~*" { + dirs := dir.GetBlock().GetDirectives() + for _, di := range dirs { + if di.GetName() == "expires" { + location.CacheTime = di.GetParameters()[0] + } + } + } + } } - if len(directive.Parameters) == 0 { - panic("no enough parameter for location") + params := directive.GetParameters() + if len(params) == 1 { + location.Match = params[0] + } else if len(params) == 2 { + location.Match = params[1] + location.Modifier = params[0] } + location.Parameters = directive.GetParameters() + location.Line = directive.GetLine() + location.Comment = directive.GetComment() + location.Directives = directives + return location +} - if len(directive.Parameters) == 1 { - location.Match = directive.Parameters[0] - return location - } else if len(directive.Parameters) == 2 { - location.Match = directive.Parameters[1] - location.Modifier = directive.Parameters[0] - return location +func (l *Location) GetName() string { + return "location" +} + +func (l *Location) GetParameters() []string { + return l.Parameters +} + +func (l *Location) GetBlock() IBlock { + return l +} + +func (l *Location) GetComment() string { + return l.Comment +} + +func (l *Location) GetLine() int { + return l.Line +} + +func (l *Location) GetDirectives() []IDirective { + return l.Directives +} + +func (l *Location) FindDirectives(directiveName string) []IDirective { + directives := make([]IDirective, 0) + for _, directive := range l.Directives { + if directive.GetName() == directiveName { + directives = append(directives, directive) + } + if directive.GetBlock() != nil { + directives = append(directives, directive.GetBlock().FindDirectives(directiveName)...) + } } - return nil + return directives +} + +func (l *Location) UpdateDirective(key string, params []string) { + if key == "" || len(params) == 0 { + return + } + directives := l.Directives + index := -1 + for i, dir := range directives { + if dir.GetName() == key { + if IsRepeatKey(key) { + oldParams := dir.GetParameters() + if !(len(oldParams) > 0 && oldParams[0] == params[0]) { + continue + } + } + index = i + break + } + } + newDirective := &Directive{ + Name: key, + Parameters: params, + } + if index > -1 { + directives[index] = newDirective + } else { + directives = append(directives, newDirective) + } + l.Directives = directives +} + +func (l *Location) RemoveDirective(key string, params []string) { + directives := l.Directives + var newDirectives []IDirective + for _, dir := range directives { + if dir.GetName() == key { + if len(params) > 0 { + oldParams := dir.GetParameters() + if oldParams[0] == params[0] { + continue + } + } else { + continue + } + } + newDirectives = append(newDirectives, dir) + } + l.Directives = newDirectives +} + +func (l *Location) ChangePath(Modifier string, Match string) { + if Match != "" && Modifier != "" { + l.Parameters = []string{Modifier, Match} + } + if Match != "" && Modifier == "" { + l.Parameters = []string{Match} + } + l.Modifier = Modifier + l.Match = Match +} + +func (l *Location) AddCache(cacheTime string) { + l.RemoveDirective("add_header", []string{"Cache-Control", "no-cache"}) + directives := l.GetDirectives() + newDir := &Directive{ + Name: "if", + Parameters: []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}, + Block: &Block{}, + } + block := &Block{} + block.Directives = append(block.Directives, &Directive{ + Name: "expires", + Parameters: []string{cacheTime}, + }) + newDir.Block = block + directives = append(directives, newDir) + l.Directives = directives + l.UpdateDirective("proxy_ignore_headers", []string{"Set-Cookie", "Cache-Control", "expires"}) + l.UpdateDirective("proxy_cache", []string{"proxy_cache_panel"}) + l.UpdateDirective("proxy_cache_key", []string{"$host$uri$is_args$args"}) + l.UpdateDirective("proxy_cache_valid", []string{"200", "304", "301", "302", "10m"}) + l.Cache = true + l.CacheTime = cacheTime +} + +func (l *Location) RemoveCache() { + l.RemoveDirective("if", []string{"(", "$uri", "~*", `"\.(gif|png|jpg|css|js|woff|woff2)$"`, ")"}) + l.RemoveDirective("proxy_ignore_headers", []string{"Set-Cookie"}) + l.RemoveDirective("proxy_cache", []string{"proxy_cache_panel"}) + l.RemoveDirective("proxy_cache_key", []string{"$host$uri$is_args$args"}) + l.RemoveDirective("proxy_cache_valid", []string{"200"}) + + l.UpdateDirective("add_header", []string{"Cache-Control", "no-cache"}) + + l.CacheTime = "" + l.Cache = false } diff --git a/backend/utils/nginx/components/server.go b/backend/utils/nginx/components/server.go index a7b6da79d..509c6bed9 100644 --- a/backend/utils/nginx/components/server.go +++ b/backend/utils/nginx/components/server.go @@ -5,8 +5,9 @@ import ( ) type Server struct { - Comment string - Listens []*ServerListen + Comment string + Listens []*ServerListen + //Locations []*Location Directives []IDirective Line int } @@ -21,6 +22,15 @@ func NewServer(directive IDirective) (*Server, error) { switch dir.GetName() { case "listen": server.Listens = append(server.Listens, NewServerListen(dir.GetParameters(), dir.GetLine())) + //case "location": + // locationDirective := &Directive{ + // Name: "location", + // Parameters: dir.GetParameters(), + // Block: dir.GetBlock(), + // Line: dir.GetLine(), + // Comment: dir.GetComment(), + // } + // server.Locations = append(server.Locations, NewLocation(locationDirective)) default: server.Directives = append(server.Directives, dir) } @@ -51,6 +61,9 @@ func (s *Server) GetDirectives() []IDirective { for _, ls := range s.Listens { directives = append(directives, ls) } + //for _, la := range s.Locations { + // directives = append(directives, la) + //} directives = append(directives, s.Directives...) return directives } @@ -116,22 +129,14 @@ func (s *Server) RemoveDirective(key string, params []string) { directives := s.Directives var newDirectives []IDirective for _, dir := range directives { - if key == "location" { - if location, ok := dir.(*Location); ok { - if len(params) == 2 && location.Match == params[1] && location.Modifier == params[0] { - continue - } - } - } else { - if dir.GetName() == key { - if len(params) > 0 { - oldParams := dir.GetParameters() - if oldParams[0] == params[0] { - continue - } - } else { + if dir.GetName() == key { + if len(params) > 0 { + oldParams := dir.GetParameters() + if oldParams[0] == params[0] { continue } + } else { + continue } } newDirectives = append(newDirectives, dir) diff --git a/backend/utils/nginx/dumper.go b/backend/utils/nginx/dumper.go index 757eef665..f85a95e8a 100644 --- a/backend/utils/nginx/dumper.go +++ b/backend/utils/nginx/dumper.go @@ -74,7 +74,6 @@ func DumpBlock(b components.IBlock, style *Style, startLine int) string { } directives := b.GetDirectives() - for i, directive := range directives { if directive.GetLine() > line { diff --git a/backend/utils/nginx/parser/parser.go b/backend/utils/nginx/parser/parser.go index 1bc7541a4..9f55d0b4d 100644 --- a/backend/utils/nginx/parser/parser.go +++ b/backend/utils/nginx/parser/parser.go @@ -84,7 +84,6 @@ func (p *Parser) Parse() *components.Config { } func (p *Parser) parseBlock() *components.Block { - context := &components.Block{ Comment: "", Directives: make([]components.IDirective, 0), diff --git a/cmd/server/nginx_conf/cache.conf b/cmd/server/nginx_conf/cache.conf new file mode 100644 index 000000000..ef1285ba8 --- /dev/null +++ b/cmd/server/nginx_conf/cache.conf @@ -0,0 +1,12 @@ +proxy_temp_path /www/common/proxy/proxy_temp_dir; +proxy_cache_path /www/common/proxy/proxy_cache_dir levels=1:2 keys_zone=proxy_cache_panel:20m inactive=1d max_size=5g; +client_body_buffer_size 512k; +proxy_connect_timeout 60; +proxy_read_timeout 60; +proxy_send_timeout 60; +proxy_buffer_size 32k; +proxy_buffers 4 64k; +proxy_busy_buffers_size 128k; +proxy_temp_file_write_size 128k; +proxy_next_upstream error timeout invalid_header http_500 http_503 http_404; +proxy_cache proxy_cache_panel; \ No newline at end of file diff --git a/cmd/server/nginx_conf/nginx_conf.go b/cmd/server/nginx_conf/nginx_conf.go index 24f80d4d6..5df2a0a30 100644 --- a/cmd/server/nginx_conf/nginx_conf.go +++ b/cmd/server/nginx_conf/nginx_conf.go @@ -19,3 +19,12 @@ var IndexPHP []byte //go:embed rewrite/* var Rewrites embed.FS + +//go:embed cache.conf +var Cache []byte + +//go:embed proxy.conf +var Proxy []byte + +//go:embed proxy_cache.conf +var ProxyCache []byte diff --git a/cmd/server/nginx_conf/proxy.conf b/cmd/server/nginx_conf/proxy.conf new file mode 100644 index 000000000..8bd082d03 --- /dev/null +++ b/cmd/server/nginx_conf/proxy.conf @@ -0,0 +1,12 @@ +location ^~ /test { + proxy_pass http://1panel.cloud/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header REMOTE-HOST $remote_addr; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_http_version 1.1; + + add_header X-Cache $upstream_cache_status; +} diff --git a/cmd/server/nginx_conf/proxy_cache.conf b/cmd/server/nginx_conf/proxy_cache.conf new file mode 100644 index 000000000..45172d6b6 --- /dev/null +++ b/cmd/server/nginx_conf/proxy_cache.conf @@ -0,0 +1,4 @@ +proxy_ignore_headers Set-Cookie Cache-Control expires; +proxy_cache cache_one; +proxy_cache_key $host$uri$is_args$args; +proxy_cache_valid 200 304 301 302 10m; \ No newline at end of file diff --git a/cmd/server/nginx_conf/proxy_no_cache.conf b/cmd/server/nginx_conf/proxy_no_cache.conf new file mode 100644 index 000000000..597f25ac4 --- /dev/null +++ b/cmd/server/nginx_conf/proxy_no_cache.conf @@ -0,0 +1,10 @@ +set $static_fileg 0; +if ( $uri ~* "\.(gif|png|jpg|css|js|woff|woff2)$" ) +{ + set $static_fileg 1; + expires 1m; +} +if ( $static_fileg = 0 ) +{ + add_header Cache-Control no-cache; +} diff --git a/frontend/src/api/interface/website.ts b/frontend/src/api/interface/website.ts index 825e070be..6742dbcdd 100644 --- a/frontend/src/api/interface/website.ts +++ b/frontend/src/api/interface/website.ts @@ -307,4 +307,28 @@ export namespace Website { user: string; group: string; } + + export interface ProxyReq { + id: number; + } + + export interface ProxyConfig { + id: number; + operate: string; + enable: boolean; + cache: boolean; + cacheTime: number; + cacheUnit: string; + name: string; + modifier: string; + match: string; + proxyPass: string; + proxyHost: string; + filePath?: string; + replaces?: ProxReplace; + } + + interface ProxReplace { + [key: string]: string; + } } diff --git a/frontend/src/api/modules/website.ts b/frontend/src/api/modules/website.ts index 5feeb0c66..342d14ce5 100644 --- a/frontend/src/api/modules/website.ts +++ b/frontend/src/api/modules/website.ts @@ -1,6 +1,6 @@ import http from '@/api'; import { ReqPage, ResPage } from '../interface'; -import { Website } from '../interface/Website'; +import { Website } from '../interface/website'; import { File } from '../interface/file'; export const SearchWebsites = (req: Website.WebSiteSearch) => { @@ -186,3 +186,11 @@ export const UpdateWebsiteDir = (req: Website.DirUpdate) => { export const UpdateWebsiteDirPermission = (req: Website.DirPermissionUpdate) => { return http.post(`/websites/dir/permission`, req); }; + +export const GetProxyConfig = (req: Website.ProxyReq) => { + return http.post(`/websites/proxies`, req); +}; + +export const CreateProxyConfig = (req: Website.ProxyReq) => { + return http.post(`/websites/proxies/update`, req); +}; diff --git a/frontend/src/global/mimetype.ts b/frontend/src/global/mimetype.ts index 5ac8ad5f1..b34d5194c 100644 --- a/frontend/src/global/mimetype.ts +++ b/frontend/src/global/mimetype.ts @@ -1,4 +1,5 @@ import { CompressType } from '@/enums/files'; +import i18n from '@/lang'; export const Mimetypes = new Map([ ['application/zip', CompressType.Zip], @@ -110,3 +111,13 @@ export const Rewrites = [ 'shopex', 'zblog', ]; + +export const Units = [ + { label: i18n.global.t('commons.units.second'), value: 's' }, + { label: i18n.global.t('commons.units.miniute'), value: 'm' }, + { label: i18n.global.t('commons.units.hour'), value: 'h' }, + { label: i18n.global.t('commons.units.day'), value: 'd' }, + { label: i18n.global.t('commons.units.week'), value: 'w' }, + { label: i18n.global.t('commons.units.month'), value: 'M' }, + { label: i18n.global.t('commons.units.year'), value: 'Y' }, +]; diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 42bf6ffa4..8b85d7fa6 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -201,6 +201,15 @@ const message = { normal: '正常', building: '制作镜像中', }, + units: { + second: '秒', + miniute: '分钟', + hour: '小时', + day: '天', + week: '周', + month: '月', + year: '年', + }, }, menu: { home: '概览', @@ -1174,6 +1183,17 @@ const message = { userGroup: '运行用户/组', user: '用户', uGroup: '用户组', + addProxy: '添加反向代理', + proxyPath: '代理目录', + proxyPass: '目标URL', + cache: '缓存', + status: '状态', + createProxy: '创建反向代理', + editProxy: '编辑反向代理', + cacheTime: '缓存时间', + enableCache: '开启缓存', + proxyHost: '发送域名', + disabled: '已停止', }, php: { short_open_tag: '短标签支持', diff --git a/frontend/src/views/website/ssl/renew/index.vue b/frontend/src/views/website/ssl/renew/index.vue index 9dd08e955..58450c947 100644 --- a/frontend/src/views/website/ssl/renew/index.vue +++ b/frontend/src/views/website/ssl/renew/index.vue @@ -34,7 +34,7 @@ diff --git a/frontend/src/views/website/website/config/basic/proxy/index.vue b/frontend/src/views/website/website/config/basic/proxy/index.vue new file mode 100644 index 000000000..be3f3bce9 --- /dev/null +++ b/frontend/src/views/website/website/config/basic/proxy/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/frontend/src/views/website/website/default/index.vue b/frontend/src/views/website/website/default/index.vue index a5c78b066..9fcd63abe 100644 --- a/frontend/src/views/website/website/default/index.vue +++ b/frontend/src/views/website/website/default/index.vue @@ -38,7 +38,7 @@