diff --git a/frontend/src/api/ngx.ts b/frontend/src/api/ngx.ts index 8ed20597..62fb41e7 100644 --- a/frontend/src/api/ngx.ts +++ b/frontend/src/api/ngx.ts @@ -7,6 +7,10 @@ const ngx = { tokenize_config(content: string) { return http.post('/ngx/tokenize_config', {content}) + }, + + format_code(content: string) { + return http.post('/ngx/format_code', {content}) } } diff --git a/frontend/src/views/config/ConfigEdit.vue b/frontend/src/views/config/ConfigEdit.vue index 18c4dd96..25fc937e 100644 --- a/frontend/src/views/config/ConfigEdit.vue +++ b/frontend/src/views/config/ConfigEdit.vue @@ -6,6 +6,7 @@ import {computed, ref} from 'vue' import config from '@/api/config' import {message} from 'ant-design-vue' import CodeEditor from '@/components/CodeEditor/CodeEditor.vue' +import ngx from '@/api/ngx' const {$gettext, interpolate} = gettext const route = useRoute() @@ -43,6 +44,14 @@ function save() { }) } +function format_code() { + ngx.format_code(configText.value).then(r => { + configText.value = r.content + message.success($gettext('Format successfully')) + }).catch(r => { + message.error(interpolate($gettext('Format error %{msg}'), {msg: r.message ?? ''})) + }) +} @@ -54,6 +63,9 @@ function save() { Back + + Format Code + Save diff --git a/go.mod b/go.mod index 1c043883..722eefd3 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/0xJacky/Nginx-UI go 1.19 -replace github.com/tufanbarisyildirim/gonginx v0.0.0-20220829083426-44da4d61ef9a => github.com/0xJacky/gonginx v0.0.0-20230104051937-4c3a63627efb - require ( github.com/creack/pty v1.1.18 github.com/dustin/go-humanize v1.0.0 @@ -21,7 +19,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/shirou/gopsutil/v3 v3.21.7 github.com/spf13/cast v1.3.1 - github.com/tufanbarisyildirim/gonginx v0.0.0-20220829083426-44da4d61ef9a + github.com/tufanbarisyildirim/gonginx v0.0.0-20230104065106-9ae864d29eed github.com/unknwon/com v1.0.1 golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad gopkg.in/ini.v1 v1.62.0 diff --git a/go.sum b/go.sum index 50c0475d..d8d0a3d9 100644 --- a/go.sum +++ b/go.sum @@ -432,6 +432,8 @@ github.com/tklauser/numcpus v0.2.3 h1:nQ0QYpiritP6ViFhrKYsiv6VVxOpum2Gks5GhnJbS/ github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/transip/gotransip/v6 v6.2.0/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= +github.com/tufanbarisyildirim/gonginx v0.0.0-20230104065106-9ae864d29eed h1:EyT9V+boG4nI4pzIuN4AWHQNvyM1LxNS21MC1CDSfg4= +github.com/tufanbarisyildirim/gonginx v0.0.0-20230104065106-9ae864d29eed/go.mod h1:+uQMU+LMBHOQermcm/ICplG+r35Ypb6Up9iYKlvKuTE= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= diff --git a/server/api/ngx.go b/server/api/ngx.go index 5ff13569..76c700b4 100644 --- a/server/api/ngx.go +++ b/server/api/ngx.go @@ -1,33 +1,47 @@ package api import ( - "github.com/0xJacky/Nginx-UI/server/pkg/nginx" - "github.com/gin-gonic/gin" - "net/http" + "github.com/0xJacky/Nginx-UI/server/pkg/nginx" + "github.com/gin-gonic/gin" + "net/http" ) func BuildNginxConfig(c *gin.Context) { - var ngxConf nginx.NgxConfig - if !BindAndValid(c, &ngxConf) { - return - } + var ngxConf nginx.NgxConfig + if !BindAndValid(c, &ngxConf) { + return + } - c.JSON(http.StatusOK, gin.H{ - "content": ngxConf.BuildConfig(), - }) + c.JSON(http.StatusOK, gin.H{ + "content": ngxConf.BuildConfig(), + }) } func TokenizeNginxConfig(c *gin.Context) { - var json struct { - Content string `json:"content" binding:"required"` - } + var json struct { + Content string `json:"content" binding:"required"` + } - if !BindAndValid(c, &json) { - return - } + if !BindAndValid(c, &json) { + return + } - ngxConfig := nginx.ParseNgxConfigByContent(json.Content) + ngxConfig := nginx.ParseNgxConfigByContent(json.Content) - c.JSON(http.StatusOK, ngxConfig) + c.JSON(http.StatusOK, ngxConfig) } + +func FormatNginxConfig(c *gin.Context) { + var json struct { + Content string `json:"content" binding:"required"` + } + + if !BindAndValid(c, &json) { + return + } + + c.JSON(http.StatusOK, gin.H{ + "content": nginx.FmtCode(json.Content), + }) +} diff --git a/server/api/template.go b/server/api/template.go index c7b5a5cb..db6d1b04 100644 --- a/server/api/template.go +++ b/server/api/template.go @@ -1,10 +1,15 @@ package api import ( + "bufio" "github.com/0xJacky/Nginx-UI/server/pkg/nginx" "github.com/0xJacky/Nginx-UI/server/settings" + "github.com/0xJacky/Nginx-UI/template" "github.com/gin-gonic/gin" + "io" "net/http" + "path/filepath" + "regexp" "strings" ) @@ -57,3 +62,81 @@ proxy_pass http://127.0.0.1:{{ HTTP01PORT }}; "tokenized": ngxConfig, }) } + +func GetTemplateConfList(c *gin.Context) { + configs, err := template.DistFS.ReadDir("conf") + if err != nil { + ErrHandler(c, err) + return + } + type configItem struct { + Name string `json:"name"` + Description map[string]string `json:"description"` + Author string `json:"author"` + } + + var configList []configItem + for _, config := range configs { + func() { + configListItem := configItem{ + Description: make(map[string]string), + } + + file, _ := template.DistFS.Open(filepath.Join("conf", config.Name())) + defer file.Close() + r := bufio.NewReader(file) + bytes, _, err := r.ReadLine() + if err == io.EOF { + return + } + line := strings.TrimSpace(string(bytes)) + + if line != "# Nginx UI Template Start" { + return + } + var content string + for { + bytes, _, err = r.ReadLine() + if err == io.EOF { + break + } + line = strings.TrimSpace(string(bytes)) + if line == "# Nginx UI Template End" { + break + } + content += line + "\n" + } + re := regexp.MustCompile(`# (\S+): (.*)`) + matches := re.FindAllStringSubmatch(content, -1) + for _, match := range matches { + if len(match) < 3 { + continue + } + key := match[1] + switch { + case key == "Name": + configListItem.Name = match[2] + case key == "Author": + configListItem.Author = match[2] + case strings.Contains(key, "Description"): + re = regexp.MustCompile(`(\w+)\[(\w+)\]`) + matches = re.FindAllStringSubmatch(key, -1) + for _, m := range matches { + if len(m) < 3 { + continue + } + // lang => description + configListItem.Description[m[2]] = match[2] + } + } + } + + configList = append(configList, configListItem) + }() + + } + + c.JSON(http.StatusOK, gin.H{ + "data": configList, + }) +} diff --git a/server/pkg/nginx/format_code.go b/server/pkg/nginx/format_code.go index 48a4d15e..08f81f7b 100644 --- a/server/pkg/nginx/format_code.go +++ b/server/pkg/nginx/format_code.go @@ -2,9 +2,17 @@ package nginx import ( "github.com/tufanbarisyildirim/gonginx" + "github.com/tufanbarisyildirim/gonginx/parser" ) func (c *NgxConfig) FmtCode() (fmtContent string) { fmtContent = gonginx.DumpConfig(c.c, gonginx.IndentedStyle) return } + +func FmtCode(content string) (fmtContent string) { + p := parser.NewStringParser(content) + c := p.Parse() + fmtContent = gonginx.DumpConfig(c, gonginx.IndentedStyle) + return +} diff --git a/server/router/routers.go b/server/router/routers.go index e782a106..6a6986ed 100644 --- a/server/router/routers.go +++ b/server/router/routers.go @@ -60,6 +60,8 @@ func InitRouter() *gin.Engine { g.POST("ngx/build_config", api.BuildNginxConfig) // Tokenized nginx configuration to NgxConf g.POST("ngx/tokenize_config", api.TokenizeNginxConfig) + // Format nginx configuration code + g.POST("ngx/format_code", api.FormatNginxConfig) g.POST("domain/:name/enable", api.EnableDomain) g.POST("domain/:name/disable", api.DisableDomain) @@ -74,6 +76,7 @@ func InitRouter() *gin.Engine { //g.GET("backup/:id", api.GetFileBackup) g.GET("template", api.GetTemplate) + g.GET("template/configs", api.GetTemplateConfList) g.GET("cert/issue", api.IssueCert) diff --git a/template/block/codeigniter.conf b/template/block/codeigniter.conf new file mode 100644 index 00000000..349a267d --- /dev/null +++ b/template/block/codeigniter.conf @@ -0,0 +1,3 @@ +location / { + try_files $uri $uri/ /index.php; +} \ No newline at end of file diff --git a/template/block/laravel.conf b/template/block/laravel.conf new file mode 100644 index 00000000..9bacbc43 --- /dev/null +++ b/template/block/laravel.conf @@ -0,0 +1,3 @@ +location / { + try_files $uri $uri/ /server.php?$query_string; +} diff --git a/template/conf/nginx-ui.conf b/template/conf/nginx-ui.conf new file mode 100644 index 00000000..ea38c4e8 --- /dev/null +++ b/template/conf/nginx-ui.conf @@ -0,0 +1,33 @@ +# Nginx UI Template Start +# Name: Nginx UI +# Description[en]: Nginx UI Config Template +# Description[zh_CN]: Nginx UI 配置模板 +# Author: @0xJacky +# Nginx UI Template End +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} +server { + listen 80; + listen [::]:80; + server_name ; + rewrite ^(.*)$ https://$host$1 permanent; +} +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name ; + ssl_certificate ; + ssl_certificate_key ; + location / { + 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 X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_pass http://127.0.0.1:9000/; + } +} diff --git a/template/conf/wordpress.conf b/template/conf/wordpress.conf new file mode 100644 index 00000000..d9912f78 --- /dev/null +++ b/template/conf/wordpress.conf @@ -0,0 +1,45 @@ +# Nginx UI Template Start +# Name: WordPress-PHP8.1 +# Description[en]: WordPress PHP 8.1 Config Template +# Description[zh_CN]: WordPress PHP 8.1 配置模板 +# Author: @0xJacky +# Nginx UI Template End +server { + listen 80; + listen [::]:80; + server_name ; + rewrite ^(.*)$ https://$host$1 permanent; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name ; + ssl_certificate ; + ssl_certificate_key ; + root ; + index index.php; + + location ~ [^/]\.php(/|$) { + try_files $uri =404; + fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; + fastcgi_index index.php; + include fastcgi.conf; + } + + + location / { + try_files $uri $uri/ /index.php?$args; + } + + # Add trailing slash to */wp-admin requests. + rewrite /wp-admin$ $scheme://$host$uri/ permanent; + + location /.well-known { + proxy_set_header Host $host; + proxy_set_header X-Real_IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr:$remote_port; + proxy_pass http://127.0.0.1:{{ HTTP01PORT }}; + } + +} diff --git a/template/template.go b/template/template.go index 1c424a74..43959d82 100644 --- a/template/template.go +++ b/template/template.go @@ -2,5 +2,5 @@ package template import "embed" -//go:embed * +//go:embed conf/* block/* var DistFS embed.FS