nginx_conf.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. package self_check
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "runtime"
  7. "strings"
  8. "time"
  9. "github.com/0xJacky/Nginx-UI/internal/nginx"
  10. "github.com/tufanbarisyildirim/gonginx/config"
  11. "github.com/tufanbarisyildirim/gonginx/dumper"
  12. "github.com/tufanbarisyildirim/gonginx/parser"
  13. )
  14. func resolvePath(path ...string) string {
  15. // fix #1046
  16. if runtime.GOOS == "windows" {
  17. return strings.TrimLeft(filepath.ToSlash(strings.ReplaceAll(nginx.GetConfPath(path...), nginx.GetNginxExeDir(), "")), "/")
  18. }
  19. return nginx.GetConfPath(path...)
  20. }
  21. // CheckNginxConfIncludeSites checks if nginx.conf include sites-enabled
  22. func CheckNginxConfIncludeSites() error {
  23. path := nginx.GetConfEntryPath()
  24. content, err := os.ReadFile(path)
  25. if err != nil {
  26. return ErrFailedToReadNginxConf
  27. }
  28. // parse nginx.conf
  29. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  30. c, err := p.Parse()
  31. if err != nil {
  32. return ErrParseNginxConf
  33. }
  34. // find http block
  35. for _, v := range c.Block.Directives {
  36. if v.GetName() == "http" {
  37. // find include sites-enabled
  38. for _, directive := range v.GetBlock().GetDirectives() {
  39. if directive.GetName() == "include" && len(directive.GetParameters()) > 0 &&
  40. strings.Contains(directive.GetParameters()[0].Value, "sites-enabled/*") {
  41. return nil
  42. }
  43. }
  44. return ErrNginxConfNotIncludeSitesEnabled
  45. }
  46. }
  47. return ErrNginxConfNoHttpBlock
  48. }
  49. // CheckNginxConfIncludeStreams checks if nginx.conf include streams-enabled
  50. func CheckNginxConfIncludeStreams() error {
  51. path := nginx.GetConfEntryPath()
  52. content, err := os.ReadFile(path)
  53. if err != nil {
  54. return ErrFailedToReadNginxConf
  55. }
  56. // parse nginx.conf
  57. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  58. c, err := p.Parse()
  59. if err != nil {
  60. return ErrParseNginxConf
  61. }
  62. // find http block
  63. for _, v := range c.Block.Directives {
  64. if v.GetName() == "stream" {
  65. // find include sites-enabled
  66. for _, directive := range v.GetBlock().GetDirectives() {
  67. if directive.GetName() == "include" && len(directive.GetParameters()) > 0 &&
  68. strings.Contains(directive.GetParameters()[0].Value, "streams-enabled/*") {
  69. return nil
  70. }
  71. }
  72. return ErrNginxConfNotIncludeStreamEnabled
  73. }
  74. }
  75. return ErrNginxConfNoStreamBlock
  76. }
  77. // FixNginxConfIncludeSites attempts to fix nginx.conf include sites-enabled
  78. func FixNginxConfIncludeSites() error {
  79. path := nginx.GetConfEntryPath()
  80. content, err := os.ReadFile(path)
  81. if err != nil {
  82. return ErrFailedToReadNginxConf
  83. }
  84. // create a backup file (+.bak.timestamp)
  85. backupPath := fmt.Sprintf("%s.bak.%d", path, time.Now().Unix())
  86. err = os.WriteFile(backupPath, content, 0644)
  87. if err != nil {
  88. return ErrFailedToCreateBackup
  89. }
  90. // parse nginx.conf
  91. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  92. c, err := p.Parse()
  93. if err != nil {
  94. return ErrParseNginxConf
  95. }
  96. // find http block
  97. for _, v := range c.Block.Directives {
  98. if v.GetName() == "http" {
  99. // add include sites-enabled/* to http block
  100. includeDirective := &config.Directive{
  101. Name: "include",
  102. Parameters: []config.Parameter{{Value: resolvePath("sites-enabled/*")}},
  103. }
  104. realBlock := v.GetBlock().(*config.HTTP)
  105. realBlock.Directives = append(realBlock.Directives, includeDirective)
  106. // write to file
  107. return os.WriteFile(path, []byte(dumper.DumpBlock(c.Block, dumper.IndentedStyle)), 0644)
  108. }
  109. }
  110. // if no http block, append http block with include sites-enabled/*
  111. content = append(content, fmt.Appendf(nil, "\nhttp {\n\tinclude %s;\n}\n", resolvePath("sites-enabled/*"))...)
  112. return os.WriteFile(path, content, 0644)
  113. }
  114. // FixNginxConfIncludeStreams attempts to fix nginx.conf include streams-enabled
  115. func FixNginxConfIncludeStreams() error {
  116. path := nginx.GetConfEntryPath()
  117. content, err := os.ReadFile(path)
  118. if err != nil {
  119. return ErrFailedToReadNginxConf
  120. }
  121. // create a backup file (+.bak.timestamp)
  122. backupPath := fmt.Sprintf("%s.bak.%d", path, time.Now().Unix())
  123. err = os.WriteFile(backupPath, content, 0644)
  124. if err != nil {
  125. return ErrFailedToCreateBackup
  126. }
  127. // parse nginx.conf
  128. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  129. c, err := p.Parse()
  130. if err != nil {
  131. return ErrParseNginxConf
  132. }
  133. // find stream block
  134. for _, v := range c.Block.Directives {
  135. if v.GetName() == "stream" {
  136. // add include streams-enabled/* to stream block
  137. includeDirective := &config.Directive{
  138. Name: "include",
  139. Parameters: []config.Parameter{{Value: resolvePath("streams-enabled/*")}},
  140. }
  141. realBlock := v.GetBlock().(*config.Block)
  142. realBlock.Directives = append(realBlock.Directives, includeDirective)
  143. // write to file
  144. return os.WriteFile(path, []byte(dumper.DumpBlock(c.Block, dumper.IndentedStyle)), 0644)
  145. }
  146. }
  147. // if no stream block, append stream block with include streams-enabled/*
  148. content = append(content, fmt.Appendf(nil, "\nstream {\n\tinclude %s;\n}\n", resolvePath("streams-enabled/*"))...)
  149. return os.WriteFile(path, content, 0644)
  150. }
  151. // CheckNginxConfIncludeConfD checks if nginx.conf includes conf.d directory
  152. func CheckNginxConfIncludeConfD() error {
  153. path := nginx.GetConfEntryPath()
  154. content, err := os.ReadFile(path)
  155. if err != nil {
  156. return ErrFailedToReadNginxConf
  157. }
  158. // parse nginx.conf
  159. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  160. c, err := p.Parse()
  161. if err != nil {
  162. return ErrParseNginxConf
  163. }
  164. // find http block
  165. for _, v := range c.Block.Directives {
  166. if v.GetName() == "http" {
  167. // find include conf.d
  168. for _, directive := range v.GetBlock().GetDirectives() {
  169. if directive.GetName() == "include" && len(directive.GetParameters()) > 0 &&
  170. strings.Contains(directive.GetParameters()[0].Value, "conf.d/*") {
  171. return nil
  172. }
  173. }
  174. return ErrNginxConfNotIncludeConfD
  175. }
  176. }
  177. return ErrNginxConfNoHttpBlock
  178. }
  179. // FixNginxConfIncludeConfD attempts to fix nginx.conf to include conf.d directory
  180. func FixNginxConfIncludeConfD() error {
  181. path := nginx.GetConfEntryPath()
  182. content, err := os.ReadFile(path)
  183. if err != nil {
  184. return ErrFailedToReadNginxConf
  185. }
  186. // create a backup file (+.bak.timestamp)
  187. backupPath := fmt.Sprintf("%s.bak.%d", path, time.Now().Unix())
  188. err = os.WriteFile(backupPath, content, 0644)
  189. if err != nil {
  190. return ErrFailedToCreateBackup
  191. }
  192. // parse nginx.conf
  193. p := parser.NewStringParser(string(content), parser.WithSkipValidDirectivesErr())
  194. c, err := p.Parse()
  195. if err != nil {
  196. return ErrParseNginxConf
  197. }
  198. // find http block
  199. for _, v := range c.Block.Directives {
  200. if v.GetName() == "http" {
  201. // add include conf.d/*.conf to http block
  202. includeDirective := &config.Directive{
  203. Name: "include",
  204. Parameters: []config.Parameter{{Value: resolvePath("conf.d/*.conf")}},
  205. }
  206. realBlock := v.GetBlock().(*config.HTTP)
  207. realBlock.Directives = append(realBlock.Directives, includeDirective)
  208. // write to file
  209. return os.WriteFile(path, []byte(dumper.DumpBlock(c.Block, dumper.IndentedStyle)), 0644)
  210. }
  211. }
  212. // if no http block, append http block with include conf.d/*.conf
  213. content = append(content, fmt.Appendf(nil, "\nhttp {\n\tinclude %s;\n}\n", resolvePath("conf.d/*.conf"))...)
  214. return os.WriteFile(path, content, 0644)
  215. }