mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	实现重写规则管理
This commit is contained in:
		@@ -37,6 +37,7 @@ type RPCClient struct {
 | 
				
			|||||||
	httpFirewallPolicyClients  []pb.HTTPFirewallPolicyServiceClient
 | 
						httpFirewallPolicyClients  []pb.HTTPFirewallPolicyServiceClient
 | 
				
			||||||
	httpLocationClients        []pb.HTTPLocationServiceClient
 | 
						httpLocationClients        []pb.HTTPLocationServiceClient
 | 
				
			||||||
	httpWebsocketClients       []pb.HTTPWebsocketServiceClient
 | 
						httpWebsocketClients       []pb.HTTPWebsocketServiceClient
 | 
				
			||||||
 | 
						httpRewriteRuleClients     []pb.HTTPRewriteRuleServiceClient
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
					func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			||||||
@@ -63,6 +64,7 @@ func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			|||||||
	httpFirewallPolicyClients := []pb.HTTPFirewallPolicyServiceClient{}
 | 
						httpFirewallPolicyClients := []pb.HTTPFirewallPolicyServiceClient{}
 | 
				
			||||||
	httpLocationClients := []pb.HTTPLocationServiceClient{}
 | 
						httpLocationClients := []pb.HTTPLocationServiceClient{}
 | 
				
			||||||
	httpWebsocketClients := []pb.HTTPWebsocketServiceClient{}
 | 
						httpWebsocketClients := []pb.HTTPWebsocketServiceClient{}
 | 
				
			||||||
 | 
						httpRewriteRuleClients := []pb.HTTPRewriteRuleServiceClient{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	conns := []*grpc.ClientConn{}
 | 
						conns := []*grpc.ClientConn{}
 | 
				
			||||||
	for _, endpoint := range apiConfig.RPC.Endpoints {
 | 
						for _, endpoint := range apiConfig.RPC.Endpoints {
 | 
				
			||||||
@@ -97,6 +99,7 @@ func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			|||||||
		httpFirewallPolicyClients = append(httpFirewallPolicyClients, pb.NewHTTPFirewallPolicyServiceClient(conn))
 | 
							httpFirewallPolicyClients = append(httpFirewallPolicyClients, pb.NewHTTPFirewallPolicyServiceClient(conn))
 | 
				
			||||||
		httpLocationClients = append(httpLocationClients, pb.NewHTTPLocationServiceClient(conn))
 | 
							httpLocationClients = append(httpLocationClients, pb.NewHTTPLocationServiceClient(conn))
 | 
				
			||||||
		httpWebsocketClients = append(httpWebsocketClients, pb.NewHTTPWebsocketServiceClient(conn))
 | 
							httpWebsocketClients = append(httpWebsocketClients, pb.NewHTTPWebsocketServiceClient(conn))
 | 
				
			||||||
 | 
							httpRewriteRuleClients = append(httpRewriteRuleClients, pb.NewHTTPRewriteRuleServiceClient(conn))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &RPCClient{
 | 
						return &RPCClient{
 | 
				
			||||||
@@ -120,6 +123,7 @@ func NewRPCClient(apiConfig *configs.APIConfig) (*RPCClient, error) {
 | 
				
			|||||||
		httpFirewallPolicyClients:  httpFirewallPolicyClients,
 | 
							httpFirewallPolicyClients:  httpFirewallPolicyClients,
 | 
				
			||||||
		httpLocationClients:        httpLocationClients,
 | 
							httpLocationClients:        httpLocationClients,
 | 
				
			||||||
		httpWebsocketClients:       httpWebsocketClients,
 | 
							httpWebsocketClients:       httpWebsocketClients,
 | 
				
			||||||
 | 
							httpRewriteRuleClients:     httpRewriteRuleClients,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -256,6 +260,13 @@ func (this *RPCClient) HTTPWebsocketRPC() pb.HTTPWebsocketServiceClient {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) HTTPRewriteRuleRPC() pb.HTTPRewriteRuleServiceClient {
 | 
				
			||||||
 | 
						if len(this.httpRewriteRuleClients) > 0 {
 | 
				
			||||||
 | 
							return this.httpRewriteRuleClients[rands.Int(0, len(this.httpRewriteRuleClients)-1)]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (this *RPCClient) Context(adminId int64) context.Context {
 | 
					func (this *RPCClient) Context(adminId int64) context.Context {
 | 
				
			||||||
	ctx := context.Background()
 | 
						ctx := context.Background()
 | 
				
			||||||
	m := maps.Map{
 | 
						m := maps.Map{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,6 +58,7 @@ func (this *IndexAction) RunGet(params struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (this *IndexAction) RunPost(params struct {
 | 
					func (this *IndexAction) RunPost(params struct {
 | 
				
			||||||
	ServerId  int64
 | 
						ServerId  int64
 | 
				
			||||||
 | 
						IsOn      bool
 | 
				
			||||||
	Addresses string
 | 
						Addresses string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WebId               int64
 | 
						WebId               int64
 | 
				
			||||||
@@ -82,10 +83,9 @@ func (this *IndexAction) RunPost(params struct {
 | 
				
			|||||||
			this.ErrorPage(err)
 | 
								this.ErrorPage(err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		httpConfig.IsOn = true
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						httpConfig.IsOn = params.IsOn
 | 
				
			||||||
	httpConfig.Listen = addresses
 | 
						httpConfig.Listen = addresses
 | 
				
			||||||
	configData, err := json.Marshal(httpConfig)
 | 
						configData, err := json.Marshal(httpConfig)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,7 @@ func (this *IndexAction) RunGet(params struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (this *IndexAction) RunPost(params struct {
 | 
					func (this *IndexAction) RunPost(params struct {
 | 
				
			||||||
	ServerId  int64
 | 
						ServerId  int64
 | 
				
			||||||
 | 
						IsOn      bool
 | 
				
			||||||
	Addresses string
 | 
						Addresses string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Must *actions.Must
 | 
						Must *actions.Must
 | 
				
			||||||
@@ -69,10 +70,9 @@ func (this *IndexAction) RunPost(params struct {
 | 
				
			|||||||
			this.ErrorPage(err)
 | 
								this.ErrorPage(err)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		httpsConfig.IsOn = true
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						httpsConfig.IsOn = params.IsOn
 | 
				
			||||||
	httpsConfig.Listen = addresses
 | 
						httpsConfig.Listen = addresses
 | 
				
			||||||
	configData, err := json.Marshal(httpsConfig)
 | 
						configData, err := json.Marshal(httpsConfig)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -63,6 +63,7 @@ func (this *IndexAction) RunGet(params struct {
 | 
				
			|||||||
		"type":        server.Type,
 | 
							"type":        server.Type,
 | 
				
			||||||
		"name":        server.Name,
 | 
							"name":        server.Name,
 | 
				
			||||||
		"description": server.Description,
 | 
							"description": server.Description,
 | 
				
			||||||
 | 
							"isOn":        server.IsOn,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	serverType := serverconfigs.FindServerType(server.Type)
 | 
						serverType := serverconfigs.FindServerType(server.Type)
 | 
				
			||||||
@@ -83,6 +84,7 @@ func (this *IndexAction) RunPost(params struct {
 | 
				
			|||||||
	Name        string
 | 
						Name        string
 | 
				
			||||||
	Description string
 | 
						Description string
 | 
				
			||||||
	ClusterId   int64
 | 
						ClusterId   int64
 | 
				
			||||||
 | 
						IsOn        bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Must *actions.Must
 | 
						Must *actions.Must
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
@@ -99,6 +101,7 @@ func (this *IndexAction) RunPost(params struct {
 | 
				
			|||||||
		Name:        params.Name,
 | 
							Name:        params.Name,
 | 
				
			||||||
		Description: params.Description,
 | 
							Description: params.Description,
 | 
				
			||||||
		ClusterId:   params.ClusterId,
 | 
							ClusterId:   params.ClusterId,
 | 
				
			||||||
 | 
							IsOn:        params.IsOn,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		this.ErrorPage(err)
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 创建路径规则
 | 
				
			||||||
type CreateAction struct {
 | 
					type CreateAction struct {
 | 
				
			||||||
	actionutils.ParentAction
 | 
						actionutils.ParentAction
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -22,6 +23,7 @@ func (this *CreateAction) Init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (this *CreateAction) RunGet(params struct {
 | 
					func (this *CreateAction) RunGet(params struct {
 | 
				
			||||||
	ServerId int64
 | 
						ServerId int64
 | 
				
			||||||
 | 
						ParentId int64 // 父节点
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
	webConfig, err := webutils.FindWebConfigWithServerId(this.Parent(), params.ServerId)
 | 
						webConfig, err := webutils.FindWebConfigWithServerId(this.Parent(), params.ServerId)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,7 @@ func init() {
 | 
				
			|||||||
			Get("", new(IndexAction)).
 | 
								Get("", new(IndexAction)).
 | 
				
			||||||
			GetPost("/create", new(CreateAction)).
 | 
								GetPost("/create", new(CreateAction)).
 | 
				
			||||||
			Post("/delete", new(DeleteAction)).
 | 
								Post("/delete", new(DeleteAction)).
 | 
				
			||||||
 | 
								Post("/sort", new(SortAction)).
 | 
				
			||||||
			EndAll()
 | 
								EndAll()
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,15 +79,16 @@ func (this *LocationHelper) createMenus(serverIdString string, locationIdString
 | 
				
			|||||||
		"isActive": secondMenuItem == "reverseProxy",
 | 
							"isActive": secondMenuItem == "reverseProxy",
 | 
				
			||||||
		"isOn":     locationConfig != nil && locationConfig.ReverseProxyRef != nil && locationConfig.ReverseProxyRef.IsPrior,
 | 
							"isOn":     locationConfig != nil && locationConfig.ReverseProxyRef != nil && locationConfig.ReverseProxyRef.IsPrior,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
 | 
							"name":     "-",
 | 
				
			||||||
 | 
							"url":      "",
 | 
				
			||||||
 | 
							"isActive": false,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	menuItems = append(menuItems, maps.Map{
 | 
						menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
		"name":     "重写规则",
 | 
							"name":     "重写规则",
 | 
				
			||||||
		"url":      "/servers/server/settings/locations/rewrite?serverId=" + serverIdString + "&locationId=" + locationIdString,
 | 
							"url":      "/servers/server/settings/locations/rewrite?serverId=" + serverIdString + "&locationId=" + locationIdString,
 | 
				
			||||||
		"isActive": secondMenuItem == "rewrite",
 | 
							"isActive": secondMenuItem == "rewrite",
 | 
				
			||||||
	})
 | 
							"isOn":     locationConfig != nil && locationConfig.Web != nil && len(locationConfig.Web.RewriteRefs) > 0,
 | 
				
			||||||
	menuItems = append(menuItems, maps.Map{
 | 
					 | 
				
			||||||
		"name":     "访问控制",
 | 
					 | 
				
			||||||
		"url":      "/servers/server/settings/locations/access?serverId=" + serverIdString + "&locationId=" + locationIdString,
 | 
					 | 
				
			||||||
		"isActive": secondMenuItem == "access",
 | 
					 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	menuItems = append(menuItems, maps.Map{
 | 
						menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
		"name":     "WAF",
 | 
							"name":     "WAF",
 | 
				
			||||||
@@ -102,9 +103,9 @@ func (this *LocationHelper) createMenus(serverIdString string, locationIdString
 | 
				
			|||||||
		"isOn":     locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.CacheRef != nil && locationConfig.Web.CacheRef.IsPrior,
 | 
							"isOn":     locationConfig != nil && locationConfig.Web != nil && locationConfig.Web.CacheRef != nil && locationConfig.Web.CacheRef.IsPrior,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	menuItems = append(menuItems, maps.Map{
 | 
						menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
		"name":     "-",
 | 
							"name":     "访问控制",
 | 
				
			||||||
		"url":      "",
 | 
							"url":      "/servers/server/settings/locations/access?serverId=" + serverIdString + "&locationId=" + locationIdString,
 | 
				
			||||||
		"isActive": false,
 | 
							"isActive": secondMenuItem == "access",
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	menuItems = append(menuItems, maps.Map{
 | 
						menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
		"name":     "字符编码",
 | 
							"name":     "字符编码",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package rewrite
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IndexAction struct {
 | 
					type IndexAction struct {
 | 
				
			||||||
@@ -14,7 +15,18 @@ func (this *IndexAction) Init() {
 | 
				
			|||||||
func (this *IndexAction) RunGet(params struct {
 | 
					func (this *IndexAction) RunGet(params struct {
 | 
				
			||||||
	LocationId int64
 | 
						LocationId int64
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
	// TODO
 | 
						webConfig, err := webutils.FindWebConfigWithLocationId(this.Parent(), params.LocationId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.Data["webId"] = webConfig.Id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(webConfig.RewriteRules) == 0 {
 | 
				
			||||||
 | 
							this.Data["rewriteRules"] = []interface{}{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							this.Data["rewriteRules"] = webConfig.RewriteRules
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this.Show()
 | 
						this.Show()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					package locations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SortAction struct {
 | 
				
			||||||
 | 
						actionutils.ParentAction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SortAction) RunPost(params struct {
 | 
				
			||||||
 | 
						WebId       int64
 | 
				
			||||||
 | 
						LocationIds []int64
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						if len(params.LocationIds) == 0 {
 | 
				
			||||||
 | 
							this.Success()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						webConfig, err := webutils.FindWebConfigWithId(this.Parent(), params.WebId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if webConfig == nil {
 | 
				
			||||||
 | 
							this.Success()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						refMap := map[int64]*serverconfigs.HTTPLocationRef{}
 | 
				
			||||||
 | 
						for _, ref := range webConfig.LocationRefs {
 | 
				
			||||||
 | 
							refMap[ref.LocationId] = ref
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newRefs := []*serverconfigs.HTTPLocationRef{}
 | 
				
			||||||
 | 
						for _, locationId := range params.LocationIds {
 | 
				
			||||||
 | 
							ref, ok := refMap[locationId]
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								newRefs = append(newRefs, ref)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newRefsJSON, err := json.Marshal(newRefs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebLocations(this.AdminContext(), &pb.UpdateHTTPWebLocationsRequest{
 | 
				
			||||||
 | 
							WebId:         params.WebId,
 | 
				
			||||||
 | 
							LocationsJSON: newRefsJSON,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,100 @@
 | 
				
			|||||||
 | 
					package rewrite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/actions"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreatePopupAction struct {
 | 
				
			||||||
 | 
						actionutils.ParentAction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *CreatePopupAction) Init() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *CreatePopupAction) RunGet(params struct {
 | 
				
			||||||
 | 
						WebId int64
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						this.Data["webId"] = params.WebId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Show()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *CreatePopupAction) RunPost(params struct {
 | 
				
			||||||
 | 
						WebId          int64
 | 
				
			||||||
 | 
						Pattern        string
 | 
				
			||||||
 | 
						Replace        string
 | 
				
			||||||
 | 
						Mode           string
 | 
				
			||||||
 | 
						RedirectStatus int
 | 
				
			||||||
 | 
						ProxyHost      string
 | 
				
			||||||
 | 
						IsBreak        bool
 | 
				
			||||||
 | 
						IsOn           bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Must *actions.Must
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						params.Must.
 | 
				
			||||||
 | 
							Field("pattern", params.Pattern).
 | 
				
			||||||
 | 
							Require("请输入匹配规则").
 | 
				
			||||||
 | 
							Expect(func() (message string, success bool) {
 | 
				
			||||||
 | 
								_, err := regexp.Compile(params.Pattern)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return "匹配规则错误:" + err.Error(), false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return "", true
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						params.Must.
 | 
				
			||||||
 | 
							Field("replace", params.Replace).
 | 
				
			||||||
 | 
							Require("请输入目标URL")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// web配置
 | 
				
			||||||
 | 
						webConfig, err := webutils.FindWebConfigWithId(this.Parent(), params.WebId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 创建
 | 
				
			||||||
 | 
						createResp, err := this.RPC().HTTPRewriteRuleRPC().CreateHTTPRewriteRule(this.AdminContext(), &pb.CreateHTTPRewriteRuleRequest{
 | 
				
			||||||
 | 
							Pattern:        params.Pattern,
 | 
				
			||||||
 | 
							Replace:        params.Replace,
 | 
				
			||||||
 | 
							Mode:           params.Mode,
 | 
				
			||||||
 | 
							RedirectStatus: types.Int32(params.RedirectStatus),
 | 
				
			||||||
 | 
							ProxyHost:      params.ProxyHost,
 | 
				
			||||||
 | 
							IsBreak:        params.IsBreak,
 | 
				
			||||||
 | 
							IsOn:           params.IsOn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ref := &serverconfigs.HTTPRewriteRef{
 | 
				
			||||||
 | 
							IsOn:          true,
 | 
				
			||||||
 | 
							RewriteRuleId: createResp.RewriteRuleId,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						webConfig.RewriteRefs = append(webConfig.RewriteRefs, ref)
 | 
				
			||||||
 | 
						refsJSON, err := json.Marshal(webConfig.RewriteRefs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 设置Web中的重写规则
 | 
				
			||||||
 | 
						_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.AdminContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
 | 
				
			||||||
 | 
							WebId:            params.WebId,
 | 
				
			||||||
 | 
							RewriteRulesJSON: refsJSON,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package rewrite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DeleteAction struct {
 | 
				
			||||||
 | 
						actionutils.ParentAction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *DeleteAction) RunPost(params struct {
 | 
				
			||||||
 | 
						WebId         int64
 | 
				
			||||||
 | 
						RewriteRuleId int64
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						webConfig, err := webutils.FindWebConfigWithId(this.Parent(), params.WebId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						refs := []*serverconfigs.HTTPRewriteRef{}
 | 
				
			||||||
 | 
						for _, ref := range webConfig.RewriteRefs {
 | 
				
			||||||
 | 
							if ref.RewriteRuleId == params.RewriteRuleId {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							refs = append(refs, ref)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						refsJSON, err := json.Marshal(refs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.AdminContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
 | 
				
			||||||
 | 
							WebId:            params.WebId,
 | 
				
			||||||
 | 
							RewriteRulesJSON: refsJSON,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,6 +2,7 @@ package rewrite
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IndexAction struct {
 | 
					type IndexAction struct {
 | 
				
			||||||
@@ -16,7 +17,18 @@ func (this *IndexAction) Init() {
 | 
				
			|||||||
func (this *IndexAction) RunGet(params struct {
 | 
					func (this *IndexAction) RunGet(params struct {
 | 
				
			||||||
	ServerId int64
 | 
						ServerId int64
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
	// TODO
 | 
						webConfig, err := webutils.FindWebConfigWithServerId(this.Parent(), params.ServerId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.Data["webId"] = webConfig.Id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(webConfig.RewriteRules) == 0 {
 | 
				
			||||||
 | 
							this.Data["rewriteRules"] = []interface{}{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							this.Data["rewriteRules"] = webConfig.RewriteRules
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this.Show()
 | 
						this.Show()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,10 @@ func init() {
 | 
				
			|||||||
			Helper(serverutils.NewServerHelper()).
 | 
								Helper(serverutils.NewServerHelper()).
 | 
				
			||||||
			Prefix("/servers/server/settings/rewrite").
 | 
								Prefix("/servers/server/settings/rewrite").
 | 
				
			||||||
			Get("", new(IndexAction)).
 | 
								Get("", new(IndexAction)).
 | 
				
			||||||
 | 
								GetPost("/createPopup", new(CreatePopupAction)).
 | 
				
			||||||
 | 
								GetPost("/updatePopup", new(UpdatePopupAction)).
 | 
				
			||||||
 | 
								Post("/delete", new(DeleteAction)).
 | 
				
			||||||
 | 
								Post("/sort", new(SortAction)).
 | 
				
			||||||
			EndAll()
 | 
								EndAll()
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					package rewrite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SortAction struct {
 | 
				
			||||||
 | 
						actionutils.ParentAction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *SortAction) RunPost(params struct {
 | 
				
			||||||
 | 
						WebId          int64
 | 
				
			||||||
 | 
						RewriteRuleIds []int64
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						webConfig, err := webutils.FindWebConfigWithId(this.Parent(), params.WebId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						refsMap := map[int64]*serverconfigs.HTTPRewriteRef{}
 | 
				
			||||||
 | 
						for _, ref := range webConfig.RewriteRefs {
 | 
				
			||||||
 | 
							refsMap[ref.RewriteRuleId] = ref
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						newRefs := []*serverconfigs.HTTPRewriteRef{}
 | 
				
			||||||
 | 
						for _, rewriteRuleId := range params.RewriteRuleIds {
 | 
				
			||||||
 | 
							ref, ok := refsMap[rewriteRuleId]
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								newRefs = append(newRefs, ref)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						refsJSON, err := json.Marshal(newRefs)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = this.RPC().HTTPWebRPC().UpdateHTTPWebRewriteRules(this.AdminContext(), &pb.UpdateHTTPWebRewriteRulesRequest{
 | 
				
			||||||
 | 
							WebId:            params.WebId,
 | 
				
			||||||
 | 
							RewriteRulesJSON: refsJSON,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					package rewrite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/server/settings/webutils"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/actions"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UpdatePopupAction struct {
 | 
				
			||||||
 | 
						actionutils.ParentAction
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *UpdatePopupAction) Init() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *UpdatePopupAction) RunGet(params struct {
 | 
				
			||||||
 | 
						WebId         int64
 | 
				
			||||||
 | 
						RewriteRuleId int64
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						this.Data["webId"] = params.WebId
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						webConfig, err := webutils.FindWebConfigWithId(this.Parent(), params.WebId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isFound := false
 | 
				
			||||||
 | 
						for _, rewriteRule := range webConfig.RewriteRules {
 | 
				
			||||||
 | 
							if rewriteRule.Id == params.RewriteRuleId {
 | 
				
			||||||
 | 
								this.Data["rewriteRule"] = rewriteRule
 | 
				
			||||||
 | 
								isFound = true
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !isFound {
 | 
				
			||||||
 | 
							this.WriteString("找不到要修改的重写规则")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Show()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *UpdatePopupAction) RunPost(params struct {
 | 
				
			||||||
 | 
						WebId          int64
 | 
				
			||||||
 | 
						RewriteRuleId  int64
 | 
				
			||||||
 | 
						Pattern        string
 | 
				
			||||||
 | 
						Replace        string
 | 
				
			||||||
 | 
						Mode           string
 | 
				
			||||||
 | 
						RedirectStatus int
 | 
				
			||||||
 | 
						ProxyHost      string
 | 
				
			||||||
 | 
						IsBreak        bool
 | 
				
			||||||
 | 
						IsOn           bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Must *actions.Must
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
						params.Must.
 | 
				
			||||||
 | 
							Field("pattern", params.Pattern).
 | 
				
			||||||
 | 
							Require("请输入匹配规则").
 | 
				
			||||||
 | 
							Expect(func() (message string, success bool) {
 | 
				
			||||||
 | 
								_, err := regexp.Compile(params.Pattern)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return "匹配规则错误:" + err.Error(), false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return "", true
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						params.Must.
 | 
				
			||||||
 | 
							Field("replace", params.Replace).
 | 
				
			||||||
 | 
							Require("请输入目标URL")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 修改
 | 
				
			||||||
 | 
						_, err := this.RPC().HTTPRewriteRuleRPC().UpdateHTTPRewriteRule(this.AdminContext(), &pb.UpdateHTTPRewriteRuleRequest{
 | 
				
			||||||
 | 
							RewriteRuleId:  params.RewriteRuleId,
 | 
				
			||||||
 | 
							Pattern:        params.Pattern,
 | 
				
			||||||
 | 
							Replace:        params.Replace,
 | 
				
			||||||
 | 
							Mode:           params.Mode,
 | 
				
			||||||
 | 
							RedirectStatus: types.Int32(params.RedirectStatus),
 | 
				
			||||||
 | 
							ProxyHost:      params.ProxyHost,
 | 
				
			||||||
 | 
							IsBreak:        params.IsBreak,
 | 
				
			||||||
 | 
							IsOn:           params.IsOn,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							this.ErrorPage(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.Success()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -159,12 +159,14 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
				
			|||||||
			"url":      "/servers/server/settings/http?serverId=" + serverIdString,
 | 
								"url":      "/servers/server/settings/http?serverId=" + serverIdString,
 | 
				
			||||||
			"isActive": secondMenuItem == "http",
 | 
								"isActive": secondMenuItem == "http",
 | 
				
			||||||
			"isOn":     (serverConfig.HTTP != nil && serverConfig.HTTP.IsOn && len(serverConfig.HTTP.Listen) > 0) || (serverConfig.Web != nil && serverConfig.Web.RedirectToHttps != nil && serverConfig.Web.RedirectToHttps.IsOn),
 | 
								"isOn":     (serverConfig.HTTP != nil && serverConfig.HTTP.IsOn && len(serverConfig.HTTP.Listen) > 0) || (serverConfig.Web != nil && serverConfig.Web.RedirectToHttps != nil && serverConfig.Web.RedirectToHttps.IsOn),
 | 
				
			||||||
 | 
								"isOff":    serverConfig.HTTP != nil && !serverConfig.HTTP.IsOn,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "HTTPS",
 | 
								"name":     "HTTPS",
 | 
				
			||||||
			"url":      "/servers/server/settings/https?serverId=" + serverIdString,
 | 
								"url":      "/servers/server/settings/https?serverId=" + serverIdString,
 | 
				
			||||||
			"isActive": secondMenuItem == "https",
 | 
								"isActive": secondMenuItem == "https",
 | 
				
			||||||
			"isOn":     serverConfig.HTTPS != nil && serverConfig.HTTPS.IsOn && len(serverConfig.HTTPS.Listen) > 0,
 | 
								"isOn":     serverConfig.HTTPS != nil && serverConfig.HTTPS.IsOn && len(serverConfig.HTTPS.Listen) > 0,
 | 
				
			||||||
 | 
								"isOff":    serverConfig.HTTPS != nil && !serverConfig.HTTPS.IsOn,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "Web设置",
 | 
								"name":     "Web设置",
 | 
				
			||||||
@@ -178,6 +180,11 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
				
			|||||||
			"isActive": secondMenuItem == "reverseProxy",
 | 
								"isActive": secondMenuItem == "reverseProxy",
 | 
				
			||||||
			"isOn":     serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
 | 
								"isOn":     serverConfig.ReverseProxyRef != nil && serverConfig.ReverseProxyRef.IsOn,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
 | 
								"name":     "-",
 | 
				
			||||||
 | 
								"url":      "",
 | 
				
			||||||
 | 
								"isActive": false,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "路径规则",
 | 
								"name":     "路径规则",
 | 
				
			||||||
			"url":      "/servers/server/settings/locations?serverId=" + serverIdString,
 | 
								"url":      "/servers/server/settings/locations?serverId=" + serverIdString,
 | 
				
			||||||
@@ -188,11 +195,7 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
				
			|||||||
			"name":     "重写规则",
 | 
								"name":     "重写规则",
 | 
				
			||||||
			"url":      "/servers/server/settings/rewrite?serverId=" + serverIdString,
 | 
								"url":      "/servers/server/settings/rewrite?serverId=" + serverIdString,
 | 
				
			||||||
			"isActive": secondMenuItem == "rewrite",
 | 
								"isActive": secondMenuItem == "rewrite",
 | 
				
			||||||
		})
 | 
								"isOn":     serverConfig.Web != nil && len(serverConfig.Web.RewriteRefs) > 0,
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
					 | 
				
			||||||
			"name":     "访问控制",
 | 
					 | 
				
			||||||
			"url":      "/servers/server/settings/access?serverId=" + serverIdString,
 | 
					 | 
				
			||||||
			"isActive": secondMenuItem == "access",
 | 
					 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "WAF",
 | 
								"name":     "WAF",
 | 
				
			||||||
@@ -207,9 +210,9 @@ func (this *ServerHelper) createSettingsMenu(secondMenuItem string, serverIdStri
 | 
				
			|||||||
			"isOn":     serverConfig.Web != nil && serverConfig.Web.CacheRef != nil && serverConfig.Web.CacheRef.IsOn,
 | 
								"isOn":     serverConfig.Web != nil && serverConfig.Web.CacheRef != nil && serverConfig.Web.CacheRef.IsOn,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "-",
 | 
								"name":     "访问控制",
 | 
				
			||||||
			"url":      "",
 | 
								"url":      "/servers/server/settings/access?serverId=" + serverIdString,
 | 
				
			||||||
			"isActive": false,
 | 
								"isActive": secondMenuItem == "access",
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		menuItems = append(menuItems, maps.Map{
 | 
							menuItems = append(menuItems, maps.Map{
 | 
				
			||||||
			"name":     "字符编码",
 | 
								"name":     "字符编码",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								web/public/js/components/common/sortable.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								web/public/js/components/common/sortable.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					// 给Table增加排序功能
 | 
				
			||||||
 | 
					function sortTable(callback) {
 | 
				
			||||||
 | 
						// 引入js
 | 
				
			||||||
 | 
						let jsFile = document.createElement("script")
 | 
				
			||||||
 | 
						jsFile.setAttribute("src", "/js/sortable.min.js")
 | 
				
			||||||
 | 
						jsFile.addEventListener("load", function () {
 | 
				
			||||||
 | 
							// 初始化
 | 
				
			||||||
 | 
							let box = document.querySelector("#sortable-table")
 | 
				
			||||||
 | 
							Sortable.create(box, {
 | 
				
			||||||
 | 
								draggable: "tbody",
 | 
				
			||||||
 | 
								handle: ".icon.handle",
 | 
				
			||||||
 | 
								onStart: function () {
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								onUpdate: function (event) {
 | 
				
			||||||
 | 
									let rows = box.querySelectorAll("tbody")
 | 
				
			||||||
 | 
									let rowIds = []
 | 
				
			||||||
 | 
									rows.forEach(function (row) {
 | 
				
			||||||
 | 
										rowIds.push(parseInt(row.getAttribute("v-id")))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									callback(rowIds)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						document.head.appendChild(jsFile)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -21,6 +21,11 @@ Vue.component("http-location-labels", {
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	template: `	<div class="labels-box">
 | 
						template: `	<div class="labels-box">
 | 
				
			||||||
	<!-- TODO 思考是否给各个标签加上链接 -->
 | 
						<!-- TODO 思考是否给各个标签加上链接 -->
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<!-- 基本信息 -->
 | 
				
			||||||
 | 
						<http-location-labels-label v-if="location.name != null && location.name.length > 0" :class="'olive'">{{location.name}}</http-location-labels-label>
 | 
				
			||||||
 | 
						<http-location-labels-label v-if="location.isBreak">BREAK</http-location-labels-label>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	<!-- redirectToHTTPS -->
 | 
						<!-- redirectToHTTPS -->
 | 
				
			||||||
	<http-location-labels-label v-if="location.web != null && configIsOn(location.web.redirectToHTTPS)">自动跳转HTTPS</http-location-labels-label>
 | 
						<http-location-labels-label v-if="location.web != null && configIsOn(location.web.redirectToHTTPS)">自动跳转HTTPS</http-location-labels-label>
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
@@ -57,15 +62,18 @@ Vue.component("http-location-labels", {
 | 
				
			|||||||
	
 | 
						
 | 
				
			||||||
	<!-- 特殊页面 -->
 | 
						<!-- 特殊页面 -->
 | 
				
			||||||
	<div v-if="location.web != null && location.web.pages != null && location.web.pages.length > 0">
 | 
						<div v-if="location.web != null && location.web.pages != null && location.web.pages.length > 0">
 | 
				
			||||||
		<http-location-labels-label v-for="page in location.web.pages">[状态码{{page.status[0]}}] -> {{page.url}}</http-location-labels-label>
 | 
							<div v-for="page in location.web.pages" :key="page.id"><http-location-labels-label>PAGE [状态码{{page.status[0]}}] -> {{page.url}}</http-location-labels-label></div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div v-if="location.web != null && configIsOn(location.web.shutdown)">
 | 
						<div v-if="location.web != null && configIsOn(location.web.shutdown)">
 | 
				
			||||||
		<http-location-labels-label :v-class="'red'">临时关闭</http-location-labels-label>
 | 
							<http-location-labels-label :v-class="'red'">临时关闭</http-location-labels-label>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						<!-- 重写规则 -->
 | 
				
			||||||
 | 
						<!-- TODO -->
 | 
				
			||||||
</div>`
 | 
					</div>`
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.component("http-location-labels-label", {
 | 
					Vue.component("http-location-labels-label", {
 | 
				
			||||||
	props: ["v-class"],
 | 
						props: ["v-class"],
 | 
				
			||||||
	template: `<span class="ui label tiny" :class="vClass" style="font-size:0.8em;padding:4px;margin-top:0.3em;margin-bottom:0.3em"><slot></slot></span>`
 | 
						template: `<span class="ui label tiny" :class="vClass" style="font-size:0.7em;padding:4px;margin-top:0.3em;margin-bottom:0.3em"><slot></slot></span>`
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
							
								
								
									
										101
									
								
								web/public/js/components/server/http-rewrite-rule-list.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								web/public/js/components/server/http-rewrite-rule-list.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					Vue.component("http-rewrite-rule-list", {
 | 
				
			||||||
 | 
						props: ["v-web-id", "v-rewrite-rules"],
 | 
				
			||||||
 | 
						mounted: function () {
 | 
				
			||||||
 | 
							setTimeout(this.sort, 1000)
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						data: function () {
 | 
				
			||||||
 | 
							let rewriteRules = this.vRewriteRules
 | 
				
			||||||
 | 
							if (rewriteRules == null) {
 | 
				
			||||||
 | 
								rewriteRules = []
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								rewriteRules: rewriteRules
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						methods: {
 | 
				
			||||||
 | 
							updateRewriteRule: function (rewriteRuleId) {
 | 
				
			||||||
 | 
								teaweb.popup("/servers/server/settings/rewrite/updatePopup?webId=" + this.vWebId + "&rewriteRuleId=" + rewriteRuleId, {
 | 
				
			||||||
 | 
									height: "26em",
 | 
				
			||||||
 | 
									callback: function () {
 | 
				
			||||||
 | 
										window.location.reload()
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							deleteRewriteRule: function (rewriteRuleId) {
 | 
				
			||||||
 | 
								let that = this
 | 
				
			||||||
 | 
								teaweb.confirm("确定要删除此重写规则吗?", function () {
 | 
				
			||||||
 | 
									Tea.action("/servers/server/settings/rewrite/delete")
 | 
				
			||||||
 | 
										.params({
 | 
				
			||||||
 | 
											webId: that.vWebId,
 | 
				
			||||||
 | 
											rewriteRuleId: rewriteRuleId
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.post()
 | 
				
			||||||
 | 
										.refresh()
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							// 排序
 | 
				
			||||||
 | 
							sort: function () {
 | 
				
			||||||
 | 
								if (this.rewriteRules.length == 0) {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								let that = this
 | 
				
			||||||
 | 
								sortTable(function (rowIds) {
 | 
				
			||||||
 | 
									Tea.action("/servers/server/settings/rewrite/sort")
 | 
				
			||||||
 | 
										.post()
 | 
				
			||||||
 | 
										.params({
 | 
				
			||||||
 | 
											webId: that.vWebId,
 | 
				
			||||||
 | 
											rewriteRuleIds: rowIds
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.success(function () {
 | 
				
			||||||
 | 
											teaweb.success("保存成功")
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						template: `<div>
 | 
				
			||||||
 | 
						<div class="margin"></div>
 | 
				
			||||||
 | 
						<p class="comment" v-if="rewriteRules.length == 0">暂时还没有重写规则。</p>
 | 
				
			||||||
 | 
						<table class="ui table selectable" v-if="rewriteRules.length > 0" id="sortable-table">
 | 
				
			||||||
 | 
							<thead>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<th style="width:1em"></th>
 | 
				
			||||||
 | 
									<th>匹配规则</th>
 | 
				
			||||||
 | 
									<th>转发目标</th>
 | 
				
			||||||
 | 
									<th>转发方式</th>
 | 
				
			||||||
 | 
									<th class="two wide">状态</th>
 | 
				
			||||||
 | 
									<th class="two op">操作</th>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</thead>
 | 
				
			||||||
 | 
							<tbody v-for="rule in rewriteRules" :v-id="rule.id">
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td><i class="icon bars grey handle"></i></td>
 | 
				
			||||||
 | 
									<td>{{rule.pattern}}
 | 
				
			||||||
 | 
									<br/>
 | 
				
			||||||
 | 
										<http-rewrite-labels-label class="ui label tiny" v-if="rule.isBreak">BREAK</http-rewrite-labels-label>
 | 
				
			||||||
 | 
										<http-rewrite-labels-label class="ui label tiny" v-if="rule.mode == 'redirect' && rule.redirectStatus != 307">{{rule.redirectStatus}}</http-rewrite-labels-label>
 | 
				
			||||||
 | 
										<http-rewrite-labels-label class="ui label tiny" v-if="rule.proxyHost.length > 0">Host: {{rule.proxyHost}}</http-rewrite-labels-label>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
									<td>{{rule.replace}}</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<span v-if="rule.mode == 'proxy'">隐式</span>
 | 
				
			||||||
 | 
										<span v-if="rule.mode == 'redirect'">显示</span>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<label-on :v-is-on="rule.isOn"></label-on>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<a href="" @click.prevent="updateRewriteRule(rule.id)">修改</a>  
 | 
				
			||||||
 | 
										<a href="" @click.prevent="deleteRewriteRule(rule.id)">删除</a>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
 | 
						</table>
 | 
				
			||||||
 | 
						<p class="comment" v-if="rewriteRules.length > 0">拖动左侧的<i class="icon bars grey"></i>图标可以对重写规则进行排序。</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>`
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vue.component("http-rewrite-labels-label", {
 | 
				
			||||||
 | 
						props: ["v-class"],
 | 
				
			||||||
 | 
						template: `<span class="ui label tiny" :class="vClass" style="font-size:0.7em;padding:4px;margin-top:0.3em;margin-bottom:0.3em"><slot></slot></span>`
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -42,13 +42,12 @@ Vue.component("http-web-root-box", {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	template: `<div>
 | 
						template: `<div>
 | 
				
			||||||
	<p class="ui message">在这里可以设置如何分发静态文件资源。</p>
 | 
					 | 
				
			||||||
	<input type="hidden" name="rootJSON" :value="JSON.stringify(rootConfig)"/>
 | 
						<input type="hidden" name="rootJSON" :value="JSON.stringify(rootConfig)"/>
 | 
				
			||||||
	<table class="ui table selectable definition">
 | 
						<table class="ui table selectable definition">
 | 
				
			||||||
		<prior-checkbox :v-config="rootConfig" v-if="vIsLocation"></prior-checkbox>
 | 
							<prior-checkbox :v-config="rootConfig" v-if="vIsLocation"></prior-checkbox>
 | 
				
			||||||
		<tbody v-show="!vIsLocation || rootConfig.isPrior">
 | 
							<tbody v-show="!vIsLocation || rootConfig.isPrior">
 | 
				
			||||||
			<tr>
 | 
								<tr>
 | 
				
			||||||
				<td class="title">是否开启</td>
 | 
									<td class="title">是否开启静态资源分发</td>
 | 
				
			||||||
				<td>
 | 
									<td>
 | 
				
			||||||
					<div class="ui checkbox">
 | 
										<div class="ui checkbox">
 | 
				
			||||||
						<input type="checkbox" v-model="rootConfig.isOn"/>
 | 
											<input type="checkbox" v-model="rootConfig.isOn"/>
 | 
				
			||||||
@@ -59,7 +58,7 @@ Vue.component("http-web-root-box", {
 | 
				
			|||||||
		</tbody>
 | 
							</tbody>
 | 
				
			||||||
		<tbody v-show="isOn()">
 | 
							<tbody v-show="isOn()">
 | 
				
			||||||
			<tr>
 | 
								<tr>
 | 
				
			||||||
				<td class="title">文档根目录</td>
 | 
									<td class="title">静态资源根目录</td>
 | 
				
			||||||
				<td>
 | 
									<td>
 | 
				
			||||||
					<input type="text" name="root" v-model="rootConfig.dir" ref="focus" placeholder="类似于 /home/www"/>
 | 
										<input type="text" name="root" v-model="rootConfig.dir" ref="focus" placeholder="类似于 /home/www"/>
 | 
				
			||||||
					<p class="comment">可以访问此根目录下的静态资源。</p>
 | 
										<p class="comment">可以访问此根目录下的静态资源。</p>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,7 +65,7 @@
 | 
				
			|||||||
  overflow-y: auto;
 | 
					  overflow-y: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.right-box.tiny {
 | 
					.right-box.tiny {
 | 
				
			||||||
  top: 10em;
 | 
					  top: 10.4em;
 | 
				
			||||||
  left: 26.5em;
 | 
					  left: 26.5em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.right-box::-webkit-scrollbar {
 | 
					.right-box::-webkit-scrollbar {
 | 
				
			||||||
@@ -130,6 +130,7 @@ p.comment,
 | 
				
			|||||||
div.comment {
 | 
					div.comment {
 | 
				
			||||||
  color: rgba(0, 0, 0, 0.3);
 | 
					  color: rgba(0, 0, 0, 0.3);
 | 
				
			||||||
  padding-top: 0.4em;
 | 
					  padding-top: 0.4em;
 | 
				
			||||||
 | 
					  font-size: 0.9em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
p.comment em,
 | 
					p.comment em,
 | 
				
			||||||
div.comment em {
 | 
					div.comment em {
 | 
				
			||||||
@@ -584,7 +585,6 @@ select.auto-width {
 | 
				
			|||||||
    width: 100% !important;
 | 
					    width: 100% !important;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/** label **/
 | 
					 | 
				
			||||||
label[for] {
 | 
					label[for] {
 | 
				
			||||||
  cursor: pointer !important;
 | 
					  cursor: pointer !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -675,4 +675,30 @@ var.dash {
 | 
				
			|||||||
form .fields {
 | 
					form .fields {
 | 
				
			||||||
  margin-bottom: 0 !important;
 | 
					  margin-bottom: 0 !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/** 排序 **/
 | 
				
			||||||
 | 
					.sortable-ghost {
 | 
				
			||||||
 | 
					  background: #ddd !important;
 | 
				
			||||||
 | 
					  opacity: 0.1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.sortable-drag {
 | 
				
			||||||
 | 
					  opacity: 1.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.icon.handle {
 | 
				
			||||||
 | 
					  cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.label.port-label {
 | 
				
			||||||
 | 
					  margin-top: 0.4em !important;
 | 
				
			||||||
 | 
					  margin-bottom: 0.4em !important;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  line-height: 1.5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.label {
 | 
				
			||||||
 | 
					  word-break: break-all;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td .label.small {
 | 
				
			||||||
 | 
					  margin-bottom: 0.2em !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					td {
 | 
				
			||||||
 | 
					  word-break: break-all;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/*# sourceMappingURL=@layout.css.map */
 | 
					/*# sourceMappingURL=@layout.css.map */
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -64,6 +64,7 @@ tbody {
 | 
				
			|||||||
p.comment, div.comment {
 | 
					p.comment, div.comment {
 | 
				
			||||||
	color: rgba(0, 0, 0, 0.3);
 | 
						color: rgba(0, 0, 0, 0.3);
 | 
				
			||||||
	padding-top: 0.4em;
 | 
						padding-top: 0.4em;
 | 
				
			||||||
 | 
						font-size: 0.9em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
p.comment em, div.comment em {
 | 
					p.comment em, div.comment em {
 | 
				
			||||||
@@ -620,7 +621,7 @@ select.auto-width {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** label **/
 | 
					// label
 | 
				
			||||||
label[for] {
 | 
					label[for] {
 | 
				
			||||||
	cursor: pointer !important;
 | 
						cursor: pointer !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -731,3 +732,38 @@ form {
 | 
				
			|||||||
		margin-bottom: 0 !important;
 | 
							margin-bottom: 0 !important;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 排序 **/
 | 
				
			||||||
 | 
					.sortable-ghost {
 | 
				
			||||||
 | 
						background: #ddd !important;
 | 
				
			||||||
 | 
						opacity: 0.1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.sortable-drag {
 | 
				
			||||||
 | 
						opacity: 1.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.icon.handle {
 | 
				
			||||||
 | 
						cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.label.port-label {
 | 
				
			||||||
 | 
						margin-top: 0.4em !important;
 | 
				
			||||||
 | 
						margin-bottom: 0.4em !important;
 | 
				
			||||||
 | 
						display: block;
 | 
				
			||||||
 | 
						line-height: 1.5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// .label
 | 
				
			||||||
 | 
					.label {
 | 
				
			||||||
 | 
						word-break: break-all;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					td .label.small {
 | 
				
			||||||
 | 
						margin-bottom: 0.2em !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// td
 | 
				
			||||||
 | 
					td {
 | 
				
			||||||
 | 
						word-break: break-all;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -87,7 +87,7 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.right-box.tiny {
 | 
					.right-box.tiny {
 | 
				
			||||||
	top: 10em;
 | 
						top: 10.4em;
 | 
				
			||||||
	left: 26.5em;
 | 
						left: 26.5em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,16 @@
 | 
				
			|||||||
		<input type="hidden" name="webId" :value="webId"/>
 | 
							<input type="hidden" name="webId" :value="webId"/>
 | 
				
			||||||
		<input type="hidden" name="serverType" :value="serverType"/>
 | 
							<input type="hidden" name="serverType" :value="serverType"/>
 | 
				
			||||||
		<table class="ui table selectable definition">
 | 
							<table class="ui table selectable definition">
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td class="title">是否启用HTTP</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isOn" value="1" v-model="httpConfig.isOn"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tbody v-show="httpConfig.isOn">
 | 
				
			||||||
				<tr>
 | 
									<tr>
 | 
				
			||||||
					<td class="title">绑定端口 *</td>
 | 
										<td class="title">绑定端口 *</td>
 | 
				
			||||||
					<td>
 | 
										<td>
 | 
				
			||||||
@@ -20,6 +30,7 @@
 | 
				
			|||||||
						<http-redirect-to-https-box :v-redirect-to-https-config="redirectToHTTPSConfig"></http-redirect-to-https-box>
 | 
											<http-redirect-to-https-box :v-redirect-to-https-config="redirectToHTTPSConfig"></http-redirect-to-https-box>
 | 
				
			||||||
					</td>
 | 
										</td>
 | 
				
			||||||
				</tr>
 | 
									</tr>
 | 
				
			||||||
 | 
								</tbody>
 | 
				
			||||||
		</table>
 | 
							</table>
 | 
				
			||||||
		<submit-btn></submit-btn>
 | 
							<submit-btn></submit-btn>
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,12 +7,23 @@
 | 
				
			|||||||
		<input type="hidden" name="serverId" :value="serverId"/>
 | 
							<input type="hidden" name="serverId" :value="serverId"/>
 | 
				
			||||||
		<input type="hidden" name="serverType" :value="serverType"/>
 | 
							<input type="hidden" name="serverType" :value="serverType"/>
 | 
				
			||||||
		<table class="ui table selectable definition">
 | 
							<table class="ui table selectable definition">
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td class="title">是否启用HTTPS</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isOn" value="1" v-model="httpsConfig.isOn"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tbody v-show="httpsConfig.isOn">
 | 
				
			||||||
				<tr>
 | 
									<tr>
 | 
				
			||||||
					<td class="title">绑定端口 *</td>
 | 
										<td class="title">绑定端口 *</td>
 | 
				
			||||||
					<td>
 | 
										<td>
 | 
				
			||||||
						<network-addresses-box :v-server-type="serverType" :v-addresses="httpsConfig.addresses" :v-protocol="'https'"></network-addresses-box>
 | 
											<network-addresses-box :v-server-type="serverType" :v-addresses="httpsConfig.addresses" :v-protocol="'https'"></network-addresses-box>
 | 
				
			||||||
					</td>
 | 
										</td>
 | 
				
			||||||
				</tr>
 | 
									</tr>
 | 
				
			||||||
 | 
								</tbody>
 | 
				
			||||||
		</table>
 | 
							</table>
 | 
				
			||||||
		<submit-btn></submit-btn>
 | 
							<submit-btn></submit-btn>
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,6 @@
 | 
				
			|||||||
					{{typeName}}
 | 
										{{typeName}}
 | 
				
			||||||
				</td>
 | 
									</td>
 | 
				
			||||||
			</tr>
 | 
								</tr>
 | 
				
			||||||
 | 
					 | 
				
			||||||
			<tr>
 | 
								<tr>
 | 
				
			||||||
				<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
									<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
				
			||||||
			</tr>
 | 
								</tr>
 | 
				
			||||||
@@ -37,6 +36,16 @@
 | 
				
			|||||||
						<textarea name="description" rows="3" v-model="server.description"></textarea>
 | 
											<textarea name="description" rows="3" v-model="server.description"></textarea>
 | 
				
			||||||
					</td>
 | 
										</td>
 | 
				
			||||||
				</tr>
 | 
									</tr>
 | 
				
			||||||
 | 
									<tr>
 | 
				
			||||||
 | 
										<td>是否启用</td>
 | 
				
			||||||
 | 
										<td>
 | 
				
			||||||
 | 
											<div class="ui checkbox">
 | 
				
			||||||
 | 
												<input type="checkbox" name="isOn" value="1" v-model="server.isOn"/>
 | 
				
			||||||
 | 
												<label></label>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<p class="comment">可以使用此选项整体关闭当前服务。</p>
 | 
				
			||||||
 | 
										</td>
 | 
				
			||||||
 | 
									</tr>
 | 
				
			||||||
			</tbody>
 | 
								</tbody>
 | 
				
			||||||
		</table>
 | 
							</table>
 | 
				
			||||||
		<submit-btn></submit-btn>
 | 
							<submit-btn></submit-btn>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,21 +1,27 @@
 | 
				
			|||||||
{$layout}
 | 
					{$layout}
 | 
				
			||||||
 | 
					 | 
				
			||||||
{$template "/left_menu"}
 | 
					{$template "/left_menu"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{$var "header"}
 | 
				
			||||||
 | 
					<script type="text/javascript" src="/js/sortable.min.js"></script>
 | 
				
			||||||
 | 
					{$end}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="right-box">
 | 
					<div class="right-box">
 | 
				
			||||||
	{$template "menu"}
 | 
						{$template "menu"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<p class="comment" v-if="locations.length == 0">暂时还没有路径规则。</p>
 | 
						<p class="comment" v-if="locations.length == 0">暂时还没有路径规则。</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<table class="ui table selectable" v-if="locations.length > 0">
 | 
						<table class="ui table selectable" v-if="locations.length > 0" id="sortable-table">
 | 
				
			||||||
		<thead>
 | 
							<thead>
 | 
				
			||||||
			<tr>
 | 
								<tr>
 | 
				
			||||||
 | 
									<th style="width:1em"></th>
 | 
				
			||||||
				<th>匹配规则</th>
 | 
									<th>匹配规则</th>
 | 
				
			||||||
				<th class="two wide">状态</th>
 | 
									<th class="two wide">状态</th>
 | 
				
			||||||
				<th class="two op">操作</th>
 | 
									<th class="two op">操作</th>
 | 
				
			||||||
			</tr>
 | 
								</tr>
 | 
				
			||||||
		</thead>
 | 
							</thead>
 | 
				
			||||||
		<tr v-for="location in locations">
 | 
							<tbody v-for="location in locations" :v-id="location.id">
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td><i class="icon bars grey handle"></i></td>
 | 
				
			||||||
				<td>
 | 
									<td>
 | 
				
			||||||
					{{location.pattern}}
 | 
										{{location.pattern}}
 | 
				
			||||||
					<http-location-labels :v-location-config="location"></http-location-labels>
 | 
										<http-location-labels :v-location-config="location"></http-location-labels>
 | 
				
			||||||
@@ -25,8 +31,11 @@
 | 
				
			|||||||
				</td>
 | 
									</td>
 | 
				
			||||||
				<td>
 | 
									<td>
 | 
				
			||||||
					<a :href="'/servers/server/settings/locations/location?serverId=' + serverId + '&locationId=' + location.id">详情</a>  
 | 
										<a :href="'/servers/server/settings/locations/location?serverId=' + serverId + '&locationId=' + location.id">详情</a>  
 | 
				
			||||||
				<a href="" @click.prevent="deleteLocation(location.id)">删除</a>
 | 
										<a href="" @click.prevent="deleteLocation(location.id)">删除</a>  
 | 
				
			||||||
 | 
										<!--<a :href="'/servers/server/settings/locations/create?serverId=' + serverId + '&webId=' + webId + '&parentId=' + location.id" title="添加子规则">+</a>-->
 | 
				
			||||||
				</td>
 | 
									</td>
 | 
				
			||||||
			</tr>
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
	</table>
 | 
						</table>
 | 
				
			||||||
 | 
						<p class="comment" v-if="locations.length > 0">拖动左侧的<i class="icon bars grey"></i>图标可以对路径规则进行排序。</p>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -1,4 +1,8 @@
 | 
				
			|||||||
Tea.context(function () {
 | 
					Tea.context(function () {
 | 
				
			||||||
 | 
						this.$delay(function () {
 | 
				
			||||||
 | 
							this.sort()
 | 
				
			||||||
 | 
						}, 1000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 删除路径规则
 | 
						// 删除路径规则
 | 
				
			||||||
	this.deleteLocation = function (locationId) {
 | 
						this.deleteLocation = function (locationId) {
 | 
				
			||||||
		teaweb.confirm("确定要删除此路径规则吗?", function () {
 | 
							teaweb.confirm("确定要删除此路径规则吗?", function () {
 | 
				
			||||||
@@ -10,4 +14,35 @@ Tea.context(function () {
 | 
				
			|||||||
				.refresh()
 | 
									.refresh()
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 排序
 | 
				
			||||||
 | 
						this.sort = function () {
 | 
				
			||||||
 | 
							if (this.locations.length == 0) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let box = this.$find("#sortable-table")[0]
 | 
				
			||||||
 | 
							let that = this
 | 
				
			||||||
 | 
							Sortable.create(box, {
 | 
				
			||||||
 | 
								draggable: "tbody",
 | 
				
			||||||
 | 
								handle: ".icon.handle",
 | 
				
			||||||
 | 
								onStart: function () {
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								onUpdate: function (event) {
 | 
				
			||||||
 | 
									let rows = box.querySelectorAll("tbody")
 | 
				
			||||||
 | 
									let locationIds = []
 | 
				
			||||||
 | 
									rows.forEach(function (row) {
 | 
				
			||||||
 | 
										locationIds.push(parseInt(row.getAttribute("v-id")))
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									that.$post(".sort")
 | 
				
			||||||
 | 
										.params({
 | 
				
			||||||
 | 
											webId: that.webId,
 | 
				
			||||||
 | 
											locationIds: locationIds
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
										.success(function () {
 | 
				
			||||||
 | 
											teaweb.success("保存成功")
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -6,6 +6,9 @@
 | 
				
			|||||||
	{$template "../left_menu"}
 | 
						{$template "../left_menu"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<div class="right-box tiny">
 | 
						<div class="right-box tiny">
 | 
				
			||||||
		<p class="ui message">此功能暂未开放,敬请期待。</p>
 | 
							<first-menu>
 | 
				
			||||||
 | 
								<a class="item" @click.prevent="createRewriteRule()">[创建]</a>
 | 
				
			||||||
 | 
							</first-menu>
 | 
				
			||||||
 | 
							<http-rewrite-rule-list :v-web-id="webId" :v-rewrite-rules="rewriteRules"></http-rewrite-rule-list>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					Tea.context(function () {
 | 
				
			||||||
 | 
						// 创建重写规则
 | 
				
			||||||
 | 
						this.createRewriteRule = function () {
 | 
				
			||||||
 | 
							teaweb.popup("/servers/server/settings/rewrite/createPopup?webId=" + this.webId, {
 | 
				
			||||||
 | 
								height: "26em",
 | 
				
			||||||
 | 
								callback: function () {
 | 
				
			||||||
 | 
									window.location.reload()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					{$layout "layout_popup"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h3>创建重写规则</h3>
 | 
				
			||||||
 | 
					<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
				
			||||||
 | 
						<input type="hidden" name="webId" :value="webId"/>
 | 
				
			||||||
 | 
						<table class="ui table definition selectable">
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td class="title">匹配规则 *</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<input type="text" name="pattern" maxlength="500" placeholder="比如 /post/(.+)" ref="focus"/>
 | 
				
			||||||
 | 
									<p class="comment">需要符合正则表达式规范,<a href="http://teaos.cn/doc/regexp/Regexp.md" target="_blank">正则表达式语法 »</a></p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td>目标URL *</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<input type="text" name="replace" placeholder="比如 /post/${1}.html" maxlength="500"/>
 | 
				
			||||||
 | 
									<p class="comment">URL中可以包含一些<a href="http://teaos.cn/doc/proxy/Variables.md" target="_blank">内置的变量</a>,也可以是一个完整的URL,比如:http://example.com/hello。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td>转发方式</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<select class="ui dropdown auto-width" name="mode" v-model="rewriteRule.mode">
 | 
				
			||||||
 | 
										<option value="proxy">隐式</option>
 | 
				
			||||||
 | 
										<option value="redirect">显式</option>
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
									<p class="comment">隐式表示不在客户端显示重写后的URL;显式表示在客户端跳转URL,将会显示重写后的URL。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tbody v-show="moreOptionsVisible">
 | 
				
			||||||
 | 
								<tr v-show="rewriteRule.mode == 'redirect'">
 | 
				
			||||||
 | 
									<td>跳转状态码</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<select class="ui dropdown auto-width" name="redirectStatus" v-model="rewriteRule.redirectStatus">
 | 
				
			||||||
 | 
											<option v-for="status in statusOptions" :value="status.code">{{status.code}} {{status.text}}</option>
 | 
				
			||||||
 | 
										</select>
 | 
				
			||||||
 | 
										<p class="comment">通常使用默认的307即可。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr v-show="rewriteRule.mode == 'proxy'">
 | 
				
			||||||
 | 
									<td>代理主机名</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<input type="text" name="proxyHost" placeholder="比如 example.com" maxlength="100"/>
 | 
				
			||||||
 | 
										<p class="comment">如果转发的方式为隐式而且目标URL为不同的域名时需要用到此选项,用于修改被代理服务接收到的域名,默认和客户端请求的主机名一致,通常不必填写,支持<a href="http://teaos.cn/doc/proxy/Variables.md#%E8%AF%B7%E6%B1%82%E7%9B%B8%E5%85%B3%E5%8F%98%E9%87%8F" target="_blank">请求变量</a>。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>是否终止往下匹配</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isBreak" value="1" checked="checked"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<p class="comment">如果选中了此选项,一旦匹配成功,不会继续匹配其他的重写规则或路径规则。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>是否启用</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isOn" value="1" checked="checked"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
 | 
						</table>
 | 
				
			||||||
 | 
						<submit-btn></submit-btn>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					Tea.context(function () {
 | 
				
			||||||
 | 
						this.success = NotifyPopup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.rewriteRule = {
 | 
				
			||||||
 | 
							mode: "proxy",
 | 
				
			||||||
 | 
							redirectStatus: 307
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.statusOptions = [
 | 
				
			||||||
 | 
							{"code": 301, "text": "Moved Permanently"},
 | 
				
			||||||
 | 
							{"code": 308, "text": "Permanent Redirect"},
 | 
				
			||||||
 | 
							{"code": 302, "text": "Found"},
 | 
				
			||||||
 | 
							{"code": 303, "text": "See Other"},
 | 
				
			||||||
 | 
							{"code": 307, "text": "Temporary Redirect"}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -2,5 +2,8 @@
 | 
				
			|||||||
{$template "/left_menu"}
 | 
					{$template "/left_menu"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="right-box">
 | 
					<div class="right-box">
 | 
				
			||||||
	<p class="ui message">此功能暂未开放,敬请期待。</p>
 | 
						<first-menu>
 | 
				
			||||||
 | 
							<a class="item" @click.prevent="createRewriteRule()">[创建]</a>
 | 
				
			||||||
 | 
						</first-menu>
 | 
				
			||||||
 | 
						<http-rewrite-rule-list :v-web-id="webId" :v-rewrite-rules="rewriteRules"></http-rewrite-rule-list>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										11
									
								
								web/views/@default/servers/server/settings/rewrite/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								web/views/@default/servers/server/settings/rewrite/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					Tea.context(function () {
 | 
				
			||||||
 | 
						// 创建重写规则
 | 
				
			||||||
 | 
						this.createRewriteRule = function () {
 | 
				
			||||||
 | 
							teaweb.popup("/servers/server/settings/rewrite/createPopup?webId=" + this.webId, {
 | 
				
			||||||
 | 
								height: "26em",
 | 
				
			||||||
 | 
								callback: function () {
 | 
				
			||||||
 | 
									window.location.reload()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					{$layout "layout_popup"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h3>修改重写规则</h3>
 | 
				
			||||||
 | 
					<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
				
			||||||
 | 
						<input type="hidden" name="webId" :value="webId"/>
 | 
				
			||||||
 | 
						<input type="hidden" name="rewriteRuleId" :value="rewriteRule.id"/>
 | 
				
			||||||
 | 
						<table class="ui table definition selectable">
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td class="title">匹配规则 *</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<input type="text" name="pattern" maxlength="500" placeholder="比如 /post/(.+)" ref="focus" v-model="rewriteRule.pattern"/>
 | 
				
			||||||
 | 
									<p class="comment">需要符合正则表达式规范,<a href="http://teaos.cn/doc/regexp/Regexp.md" target="_blank">正则表达式语法 »</a></p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td>目标URL *</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<input type="text" name="replace" placeholder="比如 /post/${1}.html" maxlength="500" v-model="rewriteRule.replace"/>
 | 
				
			||||||
 | 
									<p class="comment">URL中可以包含一些<a href="http://teaos.cn/doc/proxy/Variables.md" target="_blank">内置的变量</a>,也可以是一个完整的URL,比如:http://example.com/hello。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td>转发方式</td>
 | 
				
			||||||
 | 
								<td>
 | 
				
			||||||
 | 
									<select class="ui dropdown auto-width" name="mode" v-model="rewriteRule.mode">
 | 
				
			||||||
 | 
										<option value="proxy">隐式</option>
 | 
				
			||||||
 | 
										<option value="redirect">显式</option>
 | 
				
			||||||
 | 
									</select>
 | 
				
			||||||
 | 
									<p class="comment">隐式表示不在客户端显示重写后的URL;显式表示在客户端跳转URL,将会显示重写后的URL。</p>
 | 
				
			||||||
 | 
								</td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tr>
 | 
				
			||||||
 | 
								<td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
				
			||||||
 | 
							</tr>
 | 
				
			||||||
 | 
							<tbody v-show="moreOptionsVisible">
 | 
				
			||||||
 | 
								<tr v-show="rewriteRule.mode == 'redirect'">
 | 
				
			||||||
 | 
									<td>跳转状态码</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<select class="ui dropdown auto-width" name="redirectStatus" v-model="rewriteRule.redirectStatus">
 | 
				
			||||||
 | 
											<option v-for="status in statusOptions" :value="status.code">{{status.code}} {{status.text}}</option>
 | 
				
			||||||
 | 
										</select>
 | 
				
			||||||
 | 
										<p class="comment">通常使用默认的307即可。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr v-show="rewriteRule.mode == 'proxy'">
 | 
				
			||||||
 | 
									<td>代理主机名</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<input type="text" name="proxyHost" placeholder="比如 example.com" maxlength="100" v-model="rewriteRule.proxyHost"/>
 | 
				
			||||||
 | 
										<p class="comment">如果转发的方式为隐式而且目标URL为不同的域名时需要用到此选项,用于修改被代理服务接收到的域名,默认和客户端请求的主机名一致,通常不必填写,支持<a href="http://teaos.cn/doc/proxy/Variables.md#%E8%AF%B7%E6%B1%82%E7%9B%B8%E5%85%B3%E5%8F%98%E9%87%8F" target="_blank">请求变量</a>。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>是否终止往下匹配</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isBreak" value="1" v-model="rewriteRule.isBreak"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<p class="comment">如果选中了此选项,一旦匹配成功,不会继续匹配其他的重写规则或路径规则。</p>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
								<tr>
 | 
				
			||||||
 | 
									<td>是否启用</td>
 | 
				
			||||||
 | 
									<td>
 | 
				
			||||||
 | 
										<div class="ui checkbox">
 | 
				
			||||||
 | 
											<input type="checkbox" name="isOn" value="1" v-model="rewriteRule.isOn"/>
 | 
				
			||||||
 | 
											<label></label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</td>
 | 
				
			||||||
 | 
								</tr>
 | 
				
			||||||
 | 
							</tbody>
 | 
				
			||||||
 | 
						</table>
 | 
				
			||||||
 | 
						<submit-btn></submit-btn>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					Tea.context(function () {
 | 
				
			||||||
 | 
						this.success = NotifyPopup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.statusOptions = [
 | 
				
			||||||
 | 
							{"code": 301, "text": "Moved Permanently"},
 | 
				
			||||||
 | 
							{"code": 308, "text": "Permanent Redirect"},
 | 
				
			||||||
 | 
							{"code": 302, "text": "Found"},
 | 
				
			||||||
 | 
							{"code": 303, "text": "See Other"},
 | 
				
			||||||
 | 
							{"code": 307, "text": "Temporary Redirect"}
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
		Reference in New Issue
	
	Block a user