mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 07:57:21 +08:00
feat: 优化网站启停
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
package nginx
|
||||
|
||||
var order = []string{"listen", "server_name", "index", "root",
|
||||
"ssl_certificate", "ssl_certificate_key", "ssl_session_timeout", "ssl_session_cache", "ssl_protocols", "ssl_ciphers", "ssl_prefer_server_ciphers", "ssl_early_data", "ssl_stapling", "ssl_stapling_verify", "ssl_trusted_certificate",
|
||||
"resolver", "error_page", "include", "if", "location", "add_header", "access_log", "error_log"}
|
||||
|
||||
const DefaultConf = `server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
index index.php index.html;
|
||||
root /www/wwwroot/default;
|
||||
# Error page
|
||||
error_page 404 /404.html;
|
||||
include enable-php-0.conf;
|
||||
# Browser cache
|
||||
location ~ .*\.(bmp|jpg|jpeg|png|gif|svg|ico|tiff|webp|avif|heif|heic|jxl)$ {
|
||||
expires 30d;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
location ~ .*\.(js|css|ttf|otf|woff|woff2|eot)$ {
|
||||
expires 6h;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
# Deny sensitive files
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.env) {
|
||||
return 404;
|
||||
}
|
||||
access_log /www/wwwlogs/default.log;
|
||||
error_log /www/wwwlogs/default.log;
|
||||
}
|
||||
`
|
||||
@@ -1,223 +0,0 @@
|
||||
package nginx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (p *Parser) GetListen() ([][]string, error) {
|
||||
directives, err := p.Find("server.listen")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result [][]string
|
||||
for _, dir := range directives {
|
||||
result = append(result, p.parameters2Slices(dir.GetParameters()))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetServerName() ([]string, error) {
|
||||
directive, err := p.FindOne("server.server_name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetIndex() ([]string, error) {
|
||||
directive, err := p.FindOne("server.index")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetIndexWithComment() ([]string, []string, error) {
|
||||
directive, err := p.FindOne("server.index")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters()), directive.GetComment(), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetRoot() (string, error) {
|
||||
directive, err := p.FindOne("server.root")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue(), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetRootWithComment() (string, []string, error) {
|
||||
directive, err := p.FindOne("server.root")
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return "", directive.GetComment(), nil
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue(), directive.GetComment(), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetIncludes() (includes []string, comments [][]string, err error) {
|
||||
directives, err := p.Find("server.include")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, dir := range directives {
|
||||
if len(dir.GetParameters()) != 1 {
|
||||
return nil, nil, fmt.Errorf("invalid include directive, expected 1 parameter but got %d", len(dir.GetParameters()))
|
||||
}
|
||||
includes = append(includes, dir.GetParameters()[0].GetValue())
|
||||
comments = append(comments, dir.GetComment())
|
||||
}
|
||||
|
||||
return includes, comments, nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetPHP() int {
|
||||
directives, err := p.Find("server.include")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
var result int
|
||||
for _, dir := range directives {
|
||||
if slices.ContainsFunc(p.parameters2Slices(dir.GetParameters()), func(s string) bool {
|
||||
return strings.HasPrefix(s, "enable-php-") && strings.HasSuffix(s, ".conf")
|
||||
}) {
|
||||
_, _ = fmt.Sscanf(dir.GetParameters()[0].GetValue(), "enable-php-%d.conf", &result)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPS() bool {
|
||||
directive, err := p.FindOne("server.ssl_certificate")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPSProtocols() []string {
|
||||
directive, err := p.FindOne("server.ssl_protocols")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return p.parameters2Slices(directive.GetParameters())
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPSCiphers() string {
|
||||
directive, err := p.FindOne("server.ssl_ciphers")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue()
|
||||
}
|
||||
|
||||
func (p *Parser) GetOCSP() bool {
|
||||
directive, err := p.FindOne("server.ssl_stapling")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue() == "on"
|
||||
}
|
||||
|
||||
func (p *Parser) GetHSTS() bool {
|
||||
directives, err := p.Find("server.add_header")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, dir := range directives {
|
||||
if slices.Contains(p.parameters2Slices(dir.GetParameters()), "Strict-Transport-Security") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) GetHTTPSRedirect() bool {
|
||||
directives, err := p.Find("server.if")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, dir := range directives {
|
||||
for _, dir2 := range dir.GetBlock().GetDirectives() {
|
||||
if dir2.GetName() == "return" && slices.Contains(p.parameters2Slices(dir2.GetParameters()), "https://$host$request_uri") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) GetAltSvc() string {
|
||||
directive, err := p.FindOne("server.add_header")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for i, param := range p.parameters2Slices(directive.GetParameters()) {
|
||||
if strings.HasPrefix(param, "Alt-Svc") && i+1 < len(p.parameters2Slices(directive.GetParameters())) {
|
||||
return p.parameters2Slices(directive.GetParameters())[i+1]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p *Parser) GetAccessLog() (string, error) {
|
||||
directive, err := p.FindOne("server.access_log")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue(), nil
|
||||
}
|
||||
|
||||
func (p *Parser) GetErrorLog() (string, error) {
|
||||
directive, err := p.FindOne("server.error_log")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(p.parameters2Slices(directive.GetParameters())) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return directive.GetParameters()[0].GetValue(), nil
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
package nginx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/tufanbarisyildirim/gonginx/config"
|
||||
"github.com/tufanbarisyildirim/gonginx/dumper"
|
||||
"github.com/tufanbarisyildirim/gonginx/parser"
|
||||
)
|
||||
|
||||
// Parser Nginx vhost 配置解析器
|
||||
type Parser struct {
|
||||
c *config.Config
|
||||
orderIndex map[string]int
|
||||
}
|
||||
|
||||
func NewParser(str ...string) (*Parser, error) {
|
||||
if len(str) == 0 {
|
||||
str = append(str, DefaultConf)
|
||||
}
|
||||
p := parser.NewStringParser(str[0], parser.WithSkipIncludeParsingErr(), parser.WithSkipValidDirectivesErr())
|
||||
c, err := p.Parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderIndex := make(map[string]int)
|
||||
for i, name := range order {
|
||||
orderIndex[name] = i
|
||||
}
|
||||
|
||||
return &Parser{c: c, orderIndex: orderIndex}, nil
|
||||
}
|
||||
|
||||
func (p *Parser) Config() *config.Config {
|
||||
return p.c
|
||||
}
|
||||
|
||||
// Find 通过表达式查找配置
|
||||
// e.g. Find("server.listen")
|
||||
func (p *Parser) Find(key string) ([]config.IDirective, error) {
|
||||
parts := strings.Split(key, ".")
|
||||
var block *config.Block
|
||||
var ok bool
|
||||
block = p.c.Block
|
||||
for i := 0; i < len(parts)-1; i++ {
|
||||
key = parts[i]
|
||||
directives := block.FindDirectives(key)
|
||||
if len(directives) == 0 {
|
||||
return nil, fmt.Errorf("given key %s not found", key)
|
||||
}
|
||||
if len(directives) > 1 {
|
||||
return nil, errors.New("multiple directives found")
|
||||
}
|
||||
block, ok = directives[0].GetBlock().(*config.Block)
|
||||
if !ok {
|
||||
return nil, errors.New("block is not *config.Block")
|
||||
}
|
||||
}
|
||||
|
||||
var result []config.IDirective
|
||||
for _, dir := range block.GetDirectives() {
|
||||
if dir.GetName() == parts[len(parts)-1] {
|
||||
result = append(result, dir)
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindOne 通过表达式查找一个配置
|
||||
// e.g. FindOne("server.server_name")
|
||||
func (p *Parser) FindOne(key string) (config.IDirective, error) {
|
||||
directives, err := p.Find(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(directives) == 0 {
|
||||
return nil, fmt.Errorf("given key %s not found", key)
|
||||
}
|
||||
|
||||
return directives[0], nil
|
||||
}
|
||||
|
||||
// Clear 通过表达式移除配置
|
||||
// e.g. Clear("server.server_name")
|
||||
func (p *Parser) Clear(key string) error {
|
||||
parts := strings.Split(key, ".")
|
||||
last := parts[len(parts)-1]
|
||||
parts = parts[:len(parts)-1]
|
||||
|
||||
var block *config.Block
|
||||
var ok bool
|
||||
block = p.c.Block
|
||||
for i := 0; i < len(parts); i++ {
|
||||
directives := block.FindDirectives(parts[i])
|
||||
if len(directives) == 0 {
|
||||
return fmt.Errorf("given key %s not found", parts[i])
|
||||
}
|
||||
if len(directives) > 1 {
|
||||
return fmt.Errorf("multiple directives found for %s", parts[i])
|
||||
}
|
||||
block, ok = directives[0].GetBlock().(*config.Block)
|
||||
if !ok {
|
||||
return errors.New("block is not *config.Block")
|
||||
}
|
||||
}
|
||||
|
||||
var newDirectives []config.IDirective
|
||||
for _, directive := range block.GetDirectives() {
|
||||
if directive.GetName() != last {
|
||||
newDirectives = append(newDirectives, directive)
|
||||
}
|
||||
}
|
||||
block.Directives = newDirectives
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set 通过表达式设置配置
|
||||
// e.g. Set("server.server_name", []directive)
|
||||
func (p *Parser) Set(key string, directives []*config.Directive, after ...string) error {
|
||||
parts := strings.Split(key, ".")
|
||||
|
||||
var block *config.Block
|
||||
var blockDirective config.IDirective
|
||||
var ok bool
|
||||
block = p.c.Block
|
||||
for i := 0; i < len(parts); i++ {
|
||||
sub := block.FindDirectives(parts[i])
|
||||
if len(sub) == 0 {
|
||||
return fmt.Errorf("given key %s not found", parts[i])
|
||||
}
|
||||
if len(sub) > 1 {
|
||||
return fmt.Errorf("multiple directives found for %s", parts[i])
|
||||
}
|
||||
block, ok = sub[0].GetBlock().(*config.Block)
|
||||
if !ok {
|
||||
return errors.New("block is not *config.Block")
|
||||
}
|
||||
blockDirective = sub[0]
|
||||
}
|
||||
|
||||
iDirectives := make([]config.IDirective, 0, len(directives))
|
||||
for _, directive := range directives {
|
||||
directive.SetParent(blockDirective)
|
||||
iDirectives = append(iDirectives, directive)
|
||||
}
|
||||
|
||||
if len(after) == 0 {
|
||||
block.Directives = append(block.Directives, iDirectives...)
|
||||
} else {
|
||||
insertIndex := -1
|
||||
for i, d := range block.Directives {
|
||||
if d.GetName() == after[0] {
|
||||
insertIndex = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if insertIndex == -1 {
|
||||
return fmt.Errorf("after directive %s not found", after[0])
|
||||
}
|
||||
|
||||
block.Directives = append(
|
||||
block.Directives[:insertIndex],
|
||||
append(iDirectives, block.Directives[insertIndex:]...)...,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) Sort() {
|
||||
p.sortDirectives(p.c.Directives, p.orderIndex)
|
||||
}
|
||||
|
||||
func (p *Parser) Dump() string {
|
||||
return dumper.DumpConfig(p.c, dumper.IndentedStyle)
|
||||
}
|
||||
|
||||
func (p *Parser) sortDirectives(directives []config.IDirective, orderIndex map[string]int) {
|
||||
slices.SortFunc(directives, func(a config.IDirective, b config.IDirective) int {
|
||||
if orderIndex[a.GetName()] != orderIndex[b.GetName()] {
|
||||
return orderIndex[a.GetName()] - orderIndex[b.GetName()]
|
||||
}
|
||||
return slices.Compare(p.parameters2Slices(a.GetParameters()), p.parameters2Slices(b.GetParameters()))
|
||||
})
|
||||
|
||||
for _, directive := range directives {
|
||||
if block, ok := directive.GetBlock().(*config.Block); ok {
|
||||
p.sortDirectives(block.Directives, orderIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) slices2Parameters(slices []string) []config.Parameter {
|
||||
var parameters []config.Parameter
|
||||
for _, slice := range slices {
|
||||
parameters = append(parameters, config.Parameter{Value: slice})
|
||||
}
|
||||
return parameters
|
||||
}
|
||||
|
||||
func (p *Parser) parameters2Slices(parameters []config.Parameter) []string {
|
||||
var s []string
|
||||
for _, parameter := range parameters {
|
||||
s = append(s, parameter.Value)
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
package nginx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/acepanel/panel/pkg/io"
|
||||
)
|
||||
|
||||
type NginxTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestNginxTestSuite(t *testing.T) {
|
||||
suite.Run(t, &NginxTestSuite{})
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestListen() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
listen, err := parser.GetListen()
|
||||
s.NoError(err)
|
||||
s.Equal([][]string{{"80"}}, listen)
|
||||
s.NoError(parser.SetListen([][]string{{"80"}, {"443"}}))
|
||||
listen, err = parser.GetListen()
|
||||
s.NoError(err)
|
||||
s.Equal([][]string{{"80"}, {"443"}}, listen)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestServerName() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
serverName, err := parser.GetServerName()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"localhost"}, serverName)
|
||||
s.NoError(parser.SetServerName([]string{"example.com"}))
|
||||
serverName, err = parser.GetServerName()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"example.com"}, serverName)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestIndex() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
index, err := parser.GetIndex()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.php", "index.html"}, index)
|
||||
s.NoError(parser.SetIndex([]string{"index.html", "index.php"}))
|
||||
index, err = parser.GetIndex()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.html", "index.php"}, index)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestIndexWithComment() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
index, comment, err := parser.GetIndexWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.php", "index.html"}, index)
|
||||
s.Equal([]string(nil), comment)
|
||||
s.NoError(parser.SetIndexWithComment([]string{"index.html", "index.php"}, []string{"# 测试"}))
|
||||
index, comment, err = parser.GetIndexWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"index.html", "index.php"}, index)
|
||||
s.Equal([]string{"# 测试"}, comment)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestRoot() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
root, err := parser.GetRoot()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwroot/default", root)
|
||||
s.NoError(parser.SetRoot("/www/wwwroot/test"))
|
||||
root, err = parser.GetRoot()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwroot/test", root)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestRootWithComment() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
root, comment, err := parser.GetRootWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwroot/default", root)
|
||||
s.Equal([]string(nil), comment)
|
||||
s.NoError(parser.SetRootWithComment("/www/wwwroot/test", []string{"# 测试"}))
|
||||
root, comment, err = parser.GetRootWithComment()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwroot/test", root)
|
||||
s.Equal([]string{"# 测试"}, comment)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestIncludes() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
includes, comments, err := parser.GetIncludes()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"enable-php-0.conf"}, includes)
|
||||
s.Equal([][]string{[]string(nil)}, comments)
|
||||
s.NoError(parser.SetIncludes([]string{"/www/server/vhost/rewrite/default.conf"}, nil))
|
||||
includes, comments, err = parser.GetIncludes()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"/www/server/vhost/rewrite/default.conf"}, includes)
|
||||
s.Equal([][]string{[]string(nil)}, comments)
|
||||
s.NoError(parser.SetIncludes([]string{"/www/server/vhost/rewrite/test.conf"}, [][]string{{"# 伪静态规则测试"}}))
|
||||
includes, comments, err = parser.GetIncludes()
|
||||
s.NoError(err)
|
||||
s.Equal([]string{"/www/server/vhost/rewrite/test.conf"}, includes)
|
||||
s.Equal([][]string{{"# 伪静态规则测试"}}, comments)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestPHP() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.Equal(0, parser.GetPHP())
|
||||
s.NoError(parser.SetPHP(80))
|
||||
s.Equal(80, parser.GetPHP())
|
||||
s.NoError(parser.SetPHP(0))
|
||||
s.Equal(0, parser.GetPHP())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTP() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
expect, err := io.Read("testdata/http.conf")
|
||||
s.NoError(err)
|
||||
s.Equal(expect, parser.Dump())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPS() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.False(parser.GetHTTPS())
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.True(parser.GetHTTPS())
|
||||
expect, err := io.Read("testdata/https.conf")
|
||||
s.NoError(err)
|
||||
s.Equal(expect, parser.Dump())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPSProtocols() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.Equal([]string{"TLSv1.2", "TLSv1.3"}, parser.GetHTTPSProtocols())
|
||||
s.NoError(parser.SetHTTPSProtocols([]string{"TLSv1.3"}))
|
||||
s.Equal([]string{"TLSv1.3"}, parser.GetHTTPSProtocols())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPSCiphers() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.Equal("ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305", parser.GetHTTPSCiphers())
|
||||
s.NoError(parser.SetHTTPSCiphers("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"))
|
||||
s.Equal("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384", parser.GetHTTPSCiphers())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestOCSP() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.False(parser.GetOCSP())
|
||||
s.NoError(parser.SetOCSP(false))
|
||||
s.False(parser.GetOCSP())
|
||||
s.NoError(parser.SetOCSP(true))
|
||||
s.True(parser.GetOCSP())
|
||||
s.NoError(parser.SetOCSP(false))
|
||||
s.False(parser.GetOCSP())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHSTS() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.False(parser.GetHSTS())
|
||||
s.NoError(parser.SetHSTS(false))
|
||||
s.False(parser.GetHSTS())
|
||||
s.NoError(parser.SetHSTS(true))
|
||||
s.True(parser.GetHSTS())
|
||||
s.NoError(parser.SetHSTS(false))
|
||||
s.False(parser.GetHSTS())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestHTTPSRedirect() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.False(parser.GetHTTPSRedirect())
|
||||
s.NoError(parser.SetHTTPRedirect(false))
|
||||
s.False(parser.GetHTTPSRedirect())
|
||||
s.NoError(parser.SetHTTPRedirect(true))
|
||||
s.True(parser.GetHTTPSRedirect())
|
||||
s.NoError(parser.SetHTTPRedirect(false))
|
||||
s.False(parser.GetHTTPSRedirect())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestAltSvc() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
s.NoError(parser.SetHTTPS("/www/server/vhost/cert/default.pem", "/www/server/vhost/cert/default.key"))
|
||||
s.Equal("", parser.GetAltSvc())
|
||||
s.NoError(parser.SetAltSvc(`'h3=":$server_port"; ma=2592000'`))
|
||||
s.Equal(`'h3=":$server_port"; ma=2592000'`, parser.GetAltSvc())
|
||||
s.NoError(parser.SetAltSvc(""))
|
||||
s.Equal("", parser.GetAltSvc())
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestAccessLog() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
log, err := parser.GetAccessLog()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwlogs/default.log", log)
|
||||
s.NoError(parser.SetAccessLog("/www/wwwlogs/access.log"))
|
||||
log, err = parser.GetAccessLog()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwlogs/access.log", log)
|
||||
}
|
||||
|
||||
func (s *NginxTestSuite) TestErrorLog() {
|
||||
parser, err := NewParser()
|
||||
s.NoError(err)
|
||||
log, err := parser.GetErrorLog()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwlogs/default.log", log)
|
||||
s.NoError(parser.SetErrorLog("/www/wwwlogs/error.log"))
|
||||
log, err = parser.GetErrorLog()
|
||||
s.NoError(err)
|
||||
s.Equal("/www/wwwlogs/error.log", log)
|
||||
}
|
||||
@@ -1,492 +0,0 @@
|
||||
package nginx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/tufanbarisyildirim/gonginx/config"
|
||||
)
|
||||
|
||||
func (p *Parser) SetListen(listen [][]string) error {
|
||||
var directives []*config.Directive
|
||||
for _, l := range listen {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "listen",
|
||||
Parameters: p.slices2Parameters(l),
|
||||
})
|
||||
}
|
||||
|
||||
if err := p.Clear("server.listen"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) SetServerName(serverName []string) error {
|
||||
if err := p.Clear("server.server_name"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "server_name",
|
||||
Parameters: p.slices2Parameters(serverName),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetIndex(index []string) error {
|
||||
if err := p.Clear("server.index"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "index",
|
||||
Parameters: p.slices2Parameters(index),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetIndexWithComment(index []string, comment []string) error {
|
||||
if err := p.Clear("server.index"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "index",
|
||||
Parameters: p.slices2Parameters(index),
|
||||
Comment: comment,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetRoot(root string) error {
|
||||
if err := p.Clear("server.root"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "root",
|
||||
Parameters: []config.Parameter{{Value: root}},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetRootWithComment(root string, comment []string) error {
|
||||
if err := p.Clear("server.root"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "root",
|
||||
Parameters: []config.Parameter{{Value: root}},
|
||||
Comment: comment,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetIncludes(includes []string, comments [][]string) error {
|
||||
if err := p.Clear("server.include"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var directives []*config.Directive
|
||||
for i, item := range includes {
|
||||
var comment []string
|
||||
if i < len(comments) {
|
||||
comment = comments[i]
|
||||
}
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "include",
|
||||
Parameters: []config.Parameter{{Value: item}},
|
||||
Comment: comment,
|
||||
})
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) SetPHP(php int) error {
|
||||
old, err := p.Find("server.include")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = p.Clear("server.include"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var directives []*config.Directive
|
||||
var foundFlag bool
|
||||
for _, item := range old {
|
||||
// 查找enable-php的配置
|
||||
if slices.ContainsFunc(p.parameters2Slices(item.GetParameters()), func(s string) bool {
|
||||
return strings.HasPrefix(s, "enable-php-") && strings.HasSuffix(s, ".conf")
|
||||
}) {
|
||||
foundFlag = true
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: item.GetName(),
|
||||
Parameters: []config.Parameter{{Value: fmt.Sprintf("enable-php-%d.conf", php)}},
|
||||
Comment: item.GetComment(),
|
||||
})
|
||||
} else {
|
||||
// 其余的原样保留
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: item.GetName(),
|
||||
Parameters: item.GetParameters(),
|
||||
Comment: item.GetComment(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到enable-php的配置,直接添加一个
|
||||
if !foundFlag {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "include",
|
||||
Parameters: []config.Parameter{{Value: fmt.Sprintf("enable-php-%d.conf", php)}},
|
||||
})
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) ClearSetHTTPS() error {
|
||||
if err := p.Clear("server.ssl_certificate"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_certificate_key"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_session_timeout"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_session_cache"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_protocols"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_ciphers"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_prefer_server_ciphers"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_early_data"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) SetHTTPS(cert, key string) error {
|
||||
if err := p.ClearSetHTTPS(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "ssl_certificate",
|
||||
Parameters: []config.Parameter{{Value: cert}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_certificate_key",
|
||||
Parameters: []config.Parameter{{Value: key}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_session_timeout",
|
||||
Parameters: []config.Parameter{{Value: "1d"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_session_cache",
|
||||
Parameters: []config.Parameter{{Value: "shared:SSL:10m"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_protocols",
|
||||
Parameters: []config.Parameter{{Value: "TLSv1.2"}, {Value: "TLSv1.3"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_ciphers",
|
||||
Parameters: []config.Parameter{{Value: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_prefer_server_ciphers",
|
||||
Parameters: []config.Parameter{{Value: "off"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_early_data",
|
||||
Parameters: []config.Parameter{{Value: "on"}},
|
||||
},
|
||||
}, "root")
|
||||
}
|
||||
|
||||
func (p *Parser) SetHTTPSProtocols(protocols []string) error {
|
||||
if err := p.Clear("server.ssl_protocols"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "ssl_protocols",
|
||||
Parameters: p.slices2Parameters(protocols),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetHTTPSCiphers(ciphers string) error {
|
||||
if err := p.Clear("server.ssl_ciphers"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "ssl_ciphers",
|
||||
Parameters: []config.Parameter{{Value: ciphers}},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetOCSP(ocsp bool) error {
|
||||
if err := p.Clear("server.ssl_stapling"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.Clear("server.ssl_stapling_verify"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ocsp {
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "ssl_stapling",
|
||||
Parameters: []config.Parameter{{Value: "on"}},
|
||||
},
|
||||
{
|
||||
Name: "ssl_stapling_verify",
|
||||
Parameters: []config.Parameter{{Value: "on"}},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) SetHSTS(hsts bool) error {
|
||||
old, err := p.Find("server.add_header")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = p.Clear("server.add_header"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var directives []*config.Directive
|
||||
var foundFlag bool
|
||||
for _, dir := range old {
|
||||
if slices.Contains(p.parameters2Slices(dir.GetParameters()), "Strict-Transport-Security") {
|
||||
foundFlag = true
|
||||
if hsts {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: dir.GetName(),
|
||||
Parameters: []config.Parameter{{Value: "Strict-Transport-Security"}, {Value: "max-age=31536000"}},
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: dir.GetName(),
|
||||
Parameters: dir.GetParameters(),
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !foundFlag && hsts {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "add_header",
|
||||
Parameters: []config.Parameter{{Value: "Strict-Transport-Security"}, {Value: "max-age=31536000"}},
|
||||
})
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) SetHTTPRedirect(httpRedirect bool) error {
|
||||
// if 重定向
|
||||
ifs, err := p.Find("server.if")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = p.Clear("server.if"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var directives []*config.Directive
|
||||
var foundFlag bool
|
||||
for _, dir := range ifs { // 所有 if
|
||||
if !httpRedirect {
|
||||
if len(dir.GetParameters()) == 3 && dir.GetParameters()[0].GetValue() == "($scheme" && dir.GetParameters()[1].GetValue() == "=" && dir.GetParameters()[2].GetValue() == "http)" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
var ifDirectives []config.IDirective
|
||||
for _, dir2 := range dir.GetBlock().GetDirectives() { // 每个 if 中所有指令
|
||||
if !httpRedirect {
|
||||
// 不启用http重定向,则判断并移除特定的return指令
|
||||
if dir2.GetName() != "return" && !slices.Contains(p.parameters2Slices(dir2.GetParameters()), "https://$host$request_uri") {
|
||||
ifDirectives = append(ifDirectives, dir2)
|
||||
}
|
||||
} else {
|
||||
// 启用http重定向,需要检查防止重复添加
|
||||
if dir2.GetName() == "return" && slices.Contains(p.parameters2Slices(dir2.GetParameters()), "https://$host$request_uri") {
|
||||
foundFlag = true
|
||||
}
|
||||
ifDirectives = append(ifDirectives, dir2)
|
||||
}
|
||||
}
|
||||
// 写回 if 指令
|
||||
if block, ok := dir.GetBlock().(*config.Block); ok {
|
||||
block.Directives = ifDirectives
|
||||
}
|
||||
directives = append(directives, &config.Directive{
|
||||
Block: dir.GetBlock(),
|
||||
Name: dir.GetName(),
|
||||
Parameters: dir.GetParameters(),
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
|
||||
if !foundFlag && httpRedirect {
|
||||
ifDir := &config.Directive{
|
||||
Name: "if",
|
||||
Block: &config.Block{},
|
||||
Parameters: []config.Parameter{{Value: "($scheme"}, {Value: "="}, {Value: "http)"}},
|
||||
}
|
||||
redirectDir := &config.Directive{
|
||||
Name: "return",
|
||||
Parameters: []config.Parameter{{Value: "308"}, {Value: "https://$host$request_uri"}},
|
||||
}
|
||||
redirectDir.SetParent(ifDir.GetParent())
|
||||
ifBlock := ifDir.GetBlock().(*config.Block)
|
||||
ifBlock.Directives = append(ifBlock.Directives, redirectDir)
|
||||
directives = append(directives, ifDir)
|
||||
}
|
||||
|
||||
if err = p.Set("server", directives); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// error_page 497 重定向
|
||||
directives = nil
|
||||
errorPages, err := p.Find("server.error_page")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = p.Clear("server.error_page"); err != nil {
|
||||
return err
|
||||
}
|
||||
var found497 bool
|
||||
for _, dir := range errorPages {
|
||||
if !httpRedirect {
|
||||
// 不启用https重定向,则判断并移除特定的return指令
|
||||
if !slices.Contains(p.parameters2Slices(dir.GetParameters()), "497") && !slices.Contains(p.parameters2Slices(dir.GetParameters()), "https://$host:$server_port$request_uri") {
|
||||
directives = append(directives, &config.Directive{
|
||||
Block: dir.GetBlock(),
|
||||
Name: dir.GetName(),
|
||||
Parameters: dir.GetParameters(),
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 启用https重定向,需要检查防止重复添加
|
||||
if slices.Contains(p.parameters2Slices(dir.GetParameters()), "497") && slices.Contains(p.parameters2Slices(dir.GetParameters()), "https://$host:$server_port$request_uri") {
|
||||
found497 = true
|
||||
}
|
||||
directives = append(directives, &config.Directive{
|
||||
Block: dir.GetBlock(),
|
||||
Name: dir.GetName(),
|
||||
Parameters: dir.GetParameters(),
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !found497 && httpRedirect {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "error_page",
|
||||
Parameters: []config.Parameter{{Value: "497"}, {Value: "=308"}, {Value: "https://$host:$server_port$request_uri"}},
|
||||
})
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) SetAltSvc(altSvc string) error {
|
||||
old, err := p.Find("server.add_header")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = p.Clear("server.add_header"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var directives []*config.Directive
|
||||
var foundFlag bool
|
||||
for _, dir := range old {
|
||||
if slices.Contains(p.parameters2Slices(dir.GetParameters()), "Alt-Svc") {
|
||||
foundFlag = true
|
||||
if altSvc != "" { // 为空表示要删除
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: dir.GetName(),
|
||||
Parameters: []config.Parameter{{Value: "Alt-Svc"}, {Value: altSvc}},
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: dir.GetName(),
|
||||
Parameters: dir.GetParameters(),
|
||||
Comment: dir.GetComment(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !foundFlag && altSvc != "" {
|
||||
directives = append(directives, &config.Directive{
|
||||
Name: "add_header",
|
||||
Parameters: []config.Parameter{{Value: "Alt-Svc"}, {Value: altSvc}},
|
||||
})
|
||||
}
|
||||
|
||||
return p.Set("server", directives)
|
||||
}
|
||||
|
||||
func (p *Parser) SetAccessLog(accessLog string) error {
|
||||
if err := p.Clear("server.access_log"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "access_log",
|
||||
Parameters: []config.Parameter{{Value: accessLog}},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Parser) SetErrorLog(errorLog string) error {
|
||||
if err := p.Clear("server.error_log"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return p.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "error_log",
|
||||
Parameters: []config.Parameter{{Value: errorLog}},
|
||||
},
|
||||
})
|
||||
}
|
||||
26
pkg/nginx/testdata/http.conf
vendored
26
pkg/nginx/testdata/http.conf
vendored
@@ -1,26 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
index index.php index.html;
|
||||
root /www/wwwroot/default;
|
||||
# Error page
|
||||
error_page 404 /404.html;
|
||||
include enable-php-0.conf;
|
||||
# Browser cache
|
||||
location ~ .*\.(bmp|jpg|jpeg|png|gif|svg|ico|tiff|webp|avif|heif|heic|jxl)$ {
|
||||
expires 30d;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
location ~ .*\.(js|css|ttf|otf|woff|woff2|eot)$ {
|
||||
expires 6h;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
# Deny sensitive files
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.env) {
|
||||
return 404;
|
||||
}
|
||||
access_log /www/wwwlogs/default.log;
|
||||
error_log /www/wwwlogs/default.log;
|
||||
}
|
||||
34
pkg/nginx/testdata/https.conf
vendored
34
pkg/nginx/testdata/https.conf
vendored
@@ -1,34 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
index index.php index.html;
|
||||
root /www/wwwroot/default;
|
||||
ssl_certificate /www/server/vhost/cert/default.pem;
|
||||
ssl_certificate_key /www/server/vhost/cert/default.key;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_early_data on;
|
||||
# Error page
|
||||
error_page 404 /404.html;
|
||||
include enable-php-0.conf;
|
||||
# Browser cache
|
||||
location ~ .*\.(bmp|jpg|jpeg|png|gif|svg|ico|tiff|webp|avif|heif|heic|jxl)$ {
|
||||
expires 30d;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
location ~ .*\.(js|css|ttf|otf|woff|woff2|eot)$ {
|
||||
expires 6h;
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
}
|
||||
# Deny sensitive files
|
||||
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.env) {
|
||||
return 404;
|
||||
}
|
||||
access_log /www/wwwlogs/default.log;
|
||||
error_log /www/wwwlogs/default.log;
|
||||
}
|
||||
@@ -108,40 +108,35 @@ func (v *baseVhost) Enable() bool {
|
||||
return root != DisablePagePath
|
||||
}
|
||||
|
||||
func (v *baseVhost) SetEnable(enable bool, siteConfig ...string) error {
|
||||
name := ""
|
||||
func (v *baseVhost) SetEnable(enable bool) error {
|
||||
path := DisablePagePath
|
||||
|
||||
if enable {
|
||||
if len(siteConfig) != 2 {
|
||||
return fmt.Errorf("site config is required to enable the vhost")
|
||||
// 尝试获取保存的根目录
|
||||
if root, err := os.ReadFile(filepath.Join(v.configDir, "root.saved")); err != nil {
|
||||
path = filepath.Join(SitesPath, filepath.Dir(v.configDir), "public") // 默认根目录
|
||||
} else {
|
||||
path = strings.TrimSpace(string(root))
|
||||
}
|
||||
} else {
|
||||
// 禁用时,保存当前根目录
|
||||
currentRoot := v.Root()
|
||||
if currentRoot != "" && currentRoot != DisablePagePath {
|
||||
if err := os.WriteFile(filepath.Join(v.configDir, "root.saved"), []byte(currentRoot), 0644); err != nil {
|
||||
return fmt.Errorf("failed to save current root: %w", err)
|
||||
}
|
||||
}
|
||||
name = siteConfig[0]
|
||||
path = siteConfig[1]
|
||||
}
|
||||
|
||||
// 设置根目录
|
||||
v.vhost.SetDirective("DocumentRoot", path)
|
||||
|
||||
// 更新 Directory 块
|
||||
dirBlock := v.vhost.GetBlock("Directory")
|
||||
if dirBlock != nil {
|
||||
dirBlock.Args = []string{path}
|
||||
} else {
|
||||
block := v.vhost.AddBlock("Directory", path)
|
||||
if block.Block != nil {
|
||||
block.Block.Directives = append(block.Block.Directives,
|
||||
&Directive{Name: "Options", Args: []string{"-Indexes", "+FollowSymLinks"}},
|
||||
&Directive{Name: "AllowOverride", Args: []string{"All"}},
|
||||
&Directive{Name: "Require", Args: []string{"all", "granted"}},
|
||||
)
|
||||
}
|
||||
if err := v.SetRoot(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置 Include 配置
|
||||
v.vhost.RemoveDirectives("IncludeOptional")
|
||||
if enable {
|
||||
v.vhost.AddDirective("IncludeOptional", fmt.Sprintf("%s/%s/config/site/*.conf", SitesPath, name))
|
||||
v.vhost.AddDirective("IncludeOptional", fmt.Sprintf("%s/site/*.conf", v.configDir))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *VhostTestSuite) TestEnable() {
|
||||
s.False(s.vhost.Enable())
|
||||
|
||||
// 重新启用
|
||||
s.NoError(s.vhost.SetEnable(true, "testsite", "/var/www/test"))
|
||||
s.NoError(s.vhost.SetEnable(true))
|
||||
s.True(s.vhost.Enable())
|
||||
}
|
||||
|
||||
|
||||
@@ -108,26 +108,29 @@ func (v *baseVhost) Enable() bool {
|
||||
return directive.GetParameters()[0].GetValue() != DisablePagePath
|
||||
}
|
||||
|
||||
func (v *baseVhost) SetEnable(enable bool, siteConfig ...string) error {
|
||||
name := ""
|
||||
func (v *baseVhost) SetEnable(enable bool) error {
|
||||
path := DisablePagePath
|
||||
|
||||
if enable {
|
||||
if len(siteConfig) != 2 {
|
||||
return fmt.Errorf("site config is required to enable the vhost")
|
||||
// 尝试获取保存的根目录
|
||||
if root, err := os.ReadFile(filepath.Join(v.configDir, "root.saved")); err != nil {
|
||||
path = filepath.Join(SitesPath, filepath.Dir(v.configDir), "public") // 默认根目录
|
||||
} else {
|
||||
path = strings.TrimSpace(string(root))
|
||||
}
|
||||
} else {
|
||||
// 禁用时,保存当前根目录
|
||||
currentRoot := v.Root()
|
||||
if currentRoot != "" && currentRoot != DisablePagePath {
|
||||
if err := os.WriteFile(filepath.Join(v.configDir, "root.saved"), []byte(currentRoot), 0644); err != nil {
|
||||
return fmt.Errorf("failed to save current root: %w", err)
|
||||
}
|
||||
}
|
||||
name = siteConfig[0]
|
||||
path = siteConfig[1]
|
||||
}
|
||||
|
||||
// 设置根目录
|
||||
_ = v.parser.Clear("server.root")
|
||||
if err := v.parser.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "root",
|
||||
Parameters: v.parser.slices2Parameters([]string{path}),
|
||||
},
|
||||
}); err != nil {
|
||||
if err := v.SetRoot(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -137,7 +140,7 @@ func (v *baseVhost) SetEnable(enable bool, siteConfig ...string) error {
|
||||
return v.parser.Set("server", []*config.Directive{
|
||||
{
|
||||
Name: "include",
|
||||
Parameters: v.parser.slices2Parameters([]string{fmt.Sprintf("%s/%s/config/site/*.conf", SitesPath, name)}),
|
||||
Parameters: v.parser.slices2Parameters([]string{fmt.Sprintf("%s/site/*.conf", v.configDir)}),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func (s *VhostTestSuite) TestEnable() {
|
||||
s.False(s.vhost.Enable())
|
||||
|
||||
// 重新启用
|
||||
s.NoError(s.vhost.SetEnable(true, "testsite", "/var/www/test"))
|
||||
s.NoError(s.vhost.SetEnable(true))
|
||||
s.True(s.vhost.Enable())
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ type Vhost interface {
|
||||
|
||||
// Enable 取启用状态
|
||||
Enable() bool
|
||||
// SetEnable 设置启用状态及网站名称和根目录
|
||||
SetEnable(enable bool, siteConfig ...string) error
|
||||
// SetEnable 设置启用状态
|
||||
SetEnable(enable bool) error
|
||||
|
||||
// Listen 取监听配置
|
||||
Listen() []Listen
|
||||
|
||||
Reference in New Issue
Block a user