Procházet zdrojové kódy

bug fix and auto detect nginx config dir path

Jacky před 4 roky
rodič
revize
0ad1b3af4b

+ 1 - 0
.gitignore

@@ -3,3 +3,4 @@
 database.db
 
 
+server/tmp/main

+ 6 - 1
server/api/api.go

@@ -1,9 +1,14 @@
 package api
 
 import (
+	"github.com/gin-gonic/gin"
 	"log"
+	"net/http"
 )
 
-func ErrorHandler(err error)  {
+func ErrorHandler(c *gin.Context, err error) {
 	log.Println(err)
+	c.JSON(http.StatusInternalServerError, gin.H{
+		"message": err.Error(),
+	})
 }

+ 0 - 1
server/api/backup.go

@@ -21,5 +21,4 @@ func GetFileBackup(c *gin.Context)  {
 	backup := model.GetBackup(com.StrTo(id).MustInt())
 
 	c.JSON(http.StatusOK, backup)
-
 }

+ 54 - 20
server/api/config.go

@@ -7,15 +7,17 @@ import (
 	"io/ioutil"
 	"log"
 	"net/http"
+	"os"
 	"path/filepath"
 	"strconv"
 )
 
 func GetConfigs(c *gin.Context) {
-	configFiles, err := ioutil.ReadDir(filepath.Join("/usr/local/etc/nginx"))
+	configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("/"))
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	var configs []gin.H
@@ -25,9 +27,9 @@ func GetConfigs(c *gin.Context) {
 
 		if !file.IsDir() && "." != file.Name()[0:1] {
 			configs = append(configs, gin.H{
-				"name":    file.Name(),
-				"size":    file.Size(),
-				"modify":  file.ModTime(),
+				"name":   file.Name(),
+				"size":   file.Size(),
+				"modify": file.ModTime(),
 			})
 		}
 	}
@@ -39,12 +41,13 @@ func GetConfigs(c *gin.Context) {
 
 func GetConfig(c *gin.Context) {
 	name := c.Param("name")
-	path := filepath.Join("/usr/local/etc/nginx", name)
+	path := filepath.Join(tool.GetNginxConfPath("/"), name)
 
 	content, err := ioutil.ReadFile(path)
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	c.JSON(http.StatusOK, gin.H{
@@ -53,51 +56,82 @@ func GetConfig(c *gin.Context) {
 
 }
 
+type AddConfigJson struct {
+	Name    string `json:"name" binding:"required"`
+	Content string `json:"content" binding:"required"`
+}
+
 func AddConfig(c *gin.Context) {
-	name := c.PostForm("name")
-	content := c.PostForm("content")
+	var request AddConfigJson
+	err := c.BindJSON(&request)
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
+
+	name := request.Name
+	content := request.Content
+
 	path := filepath.Join(tool.GetNginxConfPath("/"), name)
 
-	s, err := strconv.Unquote(`"` + content + `"`)
-	if err != nil {
-		log.Println(err)
+	log.Println(path)
+	if _, err = os.Stat(path); err == nil {
+		c.JSON(http.StatusNotAcceptable, gin.H{
+			"message": "config exist",
+		})
+		return
 	}
 
-	if s != "" {
-		err := ioutil.WriteFile(path, []byte(s), 0644)
+	if content != "" {
+		err := ioutil.WriteFile(path, []byte(content), 0644)
 		if err != nil {
-			log.Println(err)
+			ErrorHandler(c, err)
+			return
 		}
 	}
 
 	tool.ReloadNginx()
 
 	c.JSON(http.StatusOK, gin.H{
-		"message": "ok",
+		"name":    name,
+		"content": content,
 	})
 
 }
 
+type EditConfigJson struct {
+	Content string `json:"content" binding:"required"`
+}
+
 func EditConfig(c *gin.Context) {
 	name := c.Param("name")
-	content := c.PostForm("content")
+	var request EditConfigJson
+	err := c.BindJSON(&request)
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
 	path := filepath.Join(tool.GetNginxConfPath("/"), name)
+	content := request.Content
 
 	s, err := strconv.Unquote(`"` + content + `"`)
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	origContent, err := ioutil.ReadFile(path)
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	if s != "" && s != string(origContent) {
 		model.CreateBackup(path)
 		err := ioutil.WriteFile(path, []byte(s), 0644)
 		if err != nil {
-			log.Println(err)
+			ErrorHandler(c, err)
+			return
 		}
 	}
 

+ 102 - 30
server/api/domain.go

@@ -9,7 +9,6 @@ import (
 	"net/http"
 	"os"
 	"path/filepath"
-	"strconv"
 	"strings"
 )
 
@@ -17,7 +16,8 @@ func GetDomains(c *gin.Context) {
 	configFiles, err := ioutil.ReadDir(tool.GetNginxConfPath("sites-available"))
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	enabledConfig, err := ioutil.ReadDir(filepath.Join(tool.GetNginxConfPath("sites-enabled")))
@@ -28,7 +28,8 @@ func GetDomains(c *gin.Context) {
 	}
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	var configs []gin.H
@@ -67,7 +68,7 @@ func GetDomain(c *gin.Context) {
 				"message": err.Error(),
 			})
 		}
-		log.Println(err)
+		ErrorHandler(c, err)
 		return
 	}
 
@@ -79,28 +80,45 @@ func GetDomain(c *gin.Context) {
 }
 
 func AddDomain(c *gin.Context) {
-	name := c.PostForm("name")
-	SupportSSL := c.PostForm("support_ssl")
+	request := make(gin.H)
+	err := c.BindJSON(&request)
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
+
+	name := request["name"].(string)
+	path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
+	log.Println(path)
+	if _, err = os.Stat(path); err == nil {
+		c.JSON(http.StatusNotAcceptable, gin.H{
+			"message": "site exist",
+		})
+		return
+	}
+
+	SupportSSL := request["support_ssl"]
 
 	baseKeys := []string{"http_listen_port",
 		"https_listen_port",
 		"server_name",
 		"ssl_certificate", "ssl_certificate_key",
-		"root", "extra",
+		"index", "root", "extra",
 	}
 
 	tmp, err := ioutil.ReadFile("template/http-conf")
 
-	log.Println(SupportSSL)
-	if SupportSSL == "true" {
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
+
+	if SupportSSL == true {
 		tmp, err = ioutil.ReadFile("template/https-conf")
 	}
 
 	if err != nil {
-		log.Println(err)
-		c.JSON(http.StatusInternalServerError, gin.H{
-			"message": "server error",
-		})
+		ErrorHandler(c, err)
 		return
 	}
 
@@ -109,13 +127,25 @@ func AddDomain(c *gin.Context) {
 	content := template
 
 	for i := range baseKeys {
-		content = strings.Replace(content, "{{ " + baseKeys[i] +" }}",
-			c.PostForm(baseKeys[i]),
-			-1)
+		val, ok := request[baseKeys[i]]
+		replace := ""
+		if ok {
+			replace = val.(string)
+		}
+		content = strings.Replace(content, "{{ "+baseKeys[i]+" }}",
+			replace, -1)
 	}
 
 	log.Println(name, content)
 
+	err = ioutil.WriteFile(path, []byte(content), 0644)
+
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
+
+
 	c.JSON(http.StatusOK, gin.H{
 		"name": name,
 		"content": content,
@@ -124,29 +154,36 @@ func AddDomain(c *gin.Context) {
 }
 
 func EditDomain(c *gin.Context) {
+	var err error
+	var origContent []byte
 	name := c.Param("name")
-	content := c.PostForm("content")
+	request := make(gin.H)
+	err = c.BindJSON(&request)
 	path := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
 
-	s, err := strconv.Unquote(`"` + content + `"`)
-	if err != nil {
-		log.Println(err)
+	if _, err = os.Stat(path); os.IsNotExist(err) {
+		c.JSON(http.StatusNotFound, gin.H{
+			"message": "site not found",
+		})
+		return
 	}
 
-	origContent, err := ioutil.ReadFile(path)
+	origContent, err = ioutil.ReadFile(path)
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
-	if s != "" && s != string(origContent) {
+	if request["content"] != "" && request["content"] != string(origContent) {
 		model.CreateBackup(path)
-		err := ioutil.WriteFile(path, []byte(s), 0644)
+		err := ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
 		if err != nil {
-			log.Println(err)
+			ErrorHandler(c, err)
+			return
 		}
 	}
 
-	if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); os.IsExist(err) {
+	if _, err := os.Stat(filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)); err == nil {
 		tool.ReloadNginx()
 	}
 
@@ -160,13 +197,15 @@ func EnableDomain(c *gin.Context) {
 	_, err := os.Stat(configFilePath)
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	err = os.Symlink(configFilePath, enabledConfigFilePath)
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	tool.ReloadNginx()
@@ -182,13 +221,15 @@ func DisableDomain(c *gin.Context) {
 	_, err := os.Stat(enabledConfigFilePath)
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	err = os.Remove(enabledConfigFilePath)
 
 	if err != nil {
-		log.Println(err)
+		ErrorHandler(c, err)
+		return
 	}
 
 	tool.ReloadNginx()
@@ -199,5 +240,36 @@ func DisableDomain(c *gin.Context) {
 }
 
 func DeleteDomain(c *gin.Context)  {
+	var err error
+	name := c.Param("name")
+	request := make(gin.H)
+	err = c.BindJSON(request)
+	availablePath := filepath.Join(tool.GetNginxConfPath("sites-available"), name)
+	enabledPath := filepath.Join(tool.GetNginxConfPath("sites-enabled"), name)
+
+	if _, err = os.Stat(availablePath); os.IsNotExist(err) {
+		c.JSON(http.StatusNotFound, gin.H{
+			"message": "site not found",
+		})
+		return
+	}
+
+	if _, err = os.Stat(enabledPath); err == nil {
+		c.JSON(http.StatusNotAcceptable, gin.H{
+			"message": "site is enabled",
+		})
+		return
+	}
+
+	err = os.Remove(availablePath)
+
+	if err != nil {
+		ErrorHandler(c, err)
+		return
+	}
+
+	c.JSON(http.StatusOK, gin.H{
+		"message": "ok",
+	})
 
 }

+ 3 - 0
server/main.go

@@ -4,6 +4,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/model"
 	"github.com/0xJacky/Nginx-UI/router"
 	"github.com/0xJacky/Nginx-UI/settings"
+	"github.com/0xJacky/Nginx-UI/tool"
 	"log"
 )
 
@@ -14,6 +15,8 @@ func main() {
 
 	model.Init()
 
+	log.Printf("nginx config dir path: %s", tool.GetNginxConfPath(""))
+
 	err := r.Run(":" + settings.ServerSettings.HttpPort)
 
 	if err != nil {

+ 8 - 1
server/model/models.go

@@ -22,5 +22,12 @@ func Init() {
 	}
 
 	// Migrate the schema
-	db.AutoMigrate(&ConfigBackup{})
+	AutoMigrate(&ConfigBackup{})
+}
+
+func AutoMigrate(model interface{})  {
+	err := db.AutoMigrate(model)
+	if err != nil {
+		log.Fatal(err)
+	}
 }

+ 2 - 0
server/router/routers.go

@@ -26,9 +26,11 @@ func InitRouter() *gin.Engine {
 		endpoint.POST("domain/:name", api.EditDomain)
 		endpoint.POST("domain/:name/enable", api.EnableDomain)
 		endpoint.POST("domain/:name/disable", api.DisableDomain)
+		endpoint.DELETE("domain/:name", api.DeleteDomain)
 
 		endpoint.GET("configs", api.GetConfigs)
 		endpoint.GET("config/:name", api.GetConfig)
+		endpoint.POST("config", api.AddConfig)
 		endpoint.POST("config/:name", api.EditConfig)
 
 		endpoint.GET("backups", api.GetFileBackupList)

+ 3 - 1
server/template/http-conf

@@ -4,7 +4,9 @@ server {
 
     server_name {{ server_name }};
 
-    root {{ root }}
+    {{ index }}
+
+    {{ root }}
 
     # extra
     {{ extra }}

+ 5 - 3
server/template/https-conf

@@ -8,12 +8,14 @@ server {
 }
 
 server {
-    listen {{ https_listen_port }};
-    listen [::]:{{ https_listen_port }};
+    listen {{ https_listen_port }} ssl http2;
+    listen [::]:{{ https_listen_port }} ssl http2;
 
     server_name {{ server_name }};
 
-    root {{ root }}
+    {{ index }}
+
+    {{ root }}
 
     # extra
     {{ extra }}

+ 20 - 0
server/test/nginx_test.go

@@ -0,0 +1,20 @@
+package test
+
+import (
+	"fmt"
+	"log"
+	"os/exec"
+	"regexp"
+	"testing"
+)
+
+func TestGetNginx(t *testing.T)  {
+	out, err := exec.Command("nginx", "-V").CombinedOutput()
+	if err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("%s\n", out)
+
+	r, _ := regexp.Compile("--conf-path=(.*)/(.*.conf)")
+	fmt.Println(r.FindStringSubmatch(string(out))[1])
+}

+ 14 - 1
server/tool/nginx.go

@@ -5,6 +5,7 @@ import (
 	"log"
 	"os/exec"
 	"path/filepath"
+	"regexp"
 )
 
 func ReloadNginx() {
@@ -21,5 +22,17 @@ func ReloadNginx() {
 }
 
 func GetNginxConfPath(dir string) string {
-	return filepath.Join("/etc/nginx", dir)
+	out, err := exec.Command("nginx", "-V").CombinedOutput()
+	if err != nil {
+		log.Fatal(err)
+	}
+	// fmt.Printf("%s\n", out)
+
+	r, _ := regexp.Compile("--conf-path=(.*)/(.*.conf)")
+
+	confPath := r.FindStringSubmatch(string(out))[1]
+
+	// fmt.Println(confPath)
+
+	return filepath.Join(confPath, dir)
 }