make proxy yse directive and forbidden get/set admin by api

This commit is contained in:
kingecg 2023-12-14 23:47:04 +08:00
parent fab22c1c2d
commit 618a186298
7 changed files with 95 additions and 75 deletions

View File

@ -1,6 +1,7 @@
package admin package admin
import ( import (
"errors"
"net/http" "net/http"
"os" "os"
"runtime" "runtime"
@ -28,6 +29,11 @@ func setConfig(w http.ResponseWriter, r *http.Request) {
return return
} }
t := data.(model.HttpServerConfig) t := data.(model.HttpServerConfig)
if t.Name == "admin" {
w.WriteHeader(http.StatusForbidden)
resp := server.NewErrorResult(errors.New("不能通过api设置管理服务器"))
w.Write(resp)
}
err := model.SetServerConfig(&t) err := model.SetServerConfig(&t)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -46,6 +52,12 @@ func getServerConfigure(w http.ResponseWriter, r *http.Request) {
ctxData := ctx.Value(server.RequestCtxKey("data")).(map[string]interface{}) ctxData := ctx.Value(server.RequestCtxKey("data")).(map[string]interface{})
id, ok := ctxData["id"] id, ok := ctxData["id"]
if ok { if ok {
if id.(string) == "admin" {
w.WriteHeader(http.StatusForbidden)
resp := server.NewErrorResult(errors.New("不能通过api获取管理服务器配置信息"))
w.Write(resp)
return
}
data := model.GetServerConfig(id.(string)) data := model.GetServerConfig(id.(string))
/// configContent, _ := json.Marshal(data) /// configContent, _ := json.Marshal(data)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)

View File

@ -6,7 +6,6 @@ import (
"os" "os"
"git.pyer.club/kingecg/gohttpd/admin" "git.pyer.club/kingecg/gohttpd/admin"
handler "git.pyer.club/kingecg/gohttpd/hander"
"git.pyer.club/kingecg/gohttpd/model" "git.pyer.club/kingecg/gohttpd/model"
"git.pyer.club/kingecg/gohttpd/server" "git.pyer.club/kingecg/gohttpd/server"
"git.pyer.club/kingecg/gohttpd/utils" "git.pyer.club/kingecg/gohttpd/utils"
@ -22,13 +21,13 @@ func (g *GoHttp) Start() {
g.logger = gologger.GetLogger("Server") g.logger = gologger.GetLogger("Server")
g.logger.Info("start gohttpd") g.logger.Info("start gohttpd")
// if g.conf != nil { // if g.conf != nil {
adminHandler := g.assembleServerMux(conf.Admin.Paths) adminHandler := server.NewServeMux(conf.Admin)
adminHandler.(*http.ServeMux).Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux)) adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux))
g.makeServer(conf.Admin, adminHandler) g.makeServer(conf.Admin, adminHandler)
for _, server := range conf.Servers { for _, s := range conf.Servers {
sHandler := g.assembleServerMux(server.Paths) sHandler := server.NewServeMux(s)
g.makeServer(server, sHandler) g.makeServer(s, sHandler)
} }
for _, listener := range server.ServerManager { for _, listener := range server.ServerManager {
@ -52,25 +51,6 @@ func (g *GoHttp) makeServer(conf *model.HttpServerConfig, mux http.Handler) {
server.AddServer(name, ss, port) server.AddServer(name, ss, port)
} }
func (g *GoHttp) assembleServerMux(p []model.HttpPath) http.Handler {
s := http.NewServeMux()
for _, httpPath := range p {
if httpPath.Root != "" {
fileHandler := handler.NewFileHandler(handler.FileHandler{
Root: httpPath.Root,
Default: httpPath.Default,
})
s.Handle(httpPath.Path, fileHandler)
} else if len(httpPath.Upstreams) != 0 {
proxyHandler := handler.NewProxyHandler(&httpPath)
s.Handle(httpPath.Path, proxyHandler)
} else {
g.logger.Error("Not supportted server path type :", httpPath.Path)
}
}
return s
}
func (g *GoHttp) Stop() {} func (g *GoHttp) Stop() {}
func LoadConfig() { func LoadConfig() {

View File

@ -3,7 +3,6 @@ package handler
import ( import (
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"net/url"
"strconv" "strconv"
"strings" "strings"
@ -30,39 +29,34 @@ func (p *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
p.proxy[proxyIndex].ServeHTTP(w, r) p.proxy[proxyIndex].ServeHTTP(w, r)
} }
// init httputil.ReverseProxy instance and add path rewrite and add session-sticky cookie to response /*
*
init httputil.ReverseProxy instance and add path rewrite and add session-sticky cookie to response
@param upstream upstream server url
@param path http path config
@param index the proxy index in upstreams
@return httputil.ReverseProxy instance
what is the directive? its stands for update of request, like HostSchemas, Path, RemoveCookie, etc.
eg: HostSchemas $target
it stande for replace req url host and schema according to $target url. $target == upstream
*/
func makeProxy(upstream string, path *model.HttpPath, index int) *httputil.ReverseProxy { func makeProxy(upstream string, path *model.HttpPath, index int) *httputil.ReverseProxy {
p := &httputil.ReverseProxy{} p := &httputil.ReverseProxy{}
directiveHandlers := []func(r *http.Request){}
if len(path.Directives) > 0 {
for _, directive := range path.Directives {
d := strings.Replace(string(directive), "$target", upstream, 1)
dh := GetUpdaterFn(d)
if dh != nil {
directiveHandlers = append(directiveHandlers, dh)
}
}
}
p.Director = func(req *http.Request) { p.Director = func(req *http.Request) {
turl, _ := url.Parse(upstream) for _, handler := range directiveHandlers {
req.URL.Host = turl.Host handler(req)
req.URL.Scheme = turl.Scheme
pw := path.Rewrite
if pw.Replace != "" {
req.URL.Path = strings.TrimPrefix(req.URL.Path, pw.Replace)
if req.URL.RawPath != "" {
req.URL.RawPath = strings.TrimPrefix(req.URL.RawPath, pw.Replace)
}
}
if pw.With != "" {
req.URL.Path = strings.TrimSuffix(pw.With, "/") + "/" + req.URL.Path
if req.URL.RawPath != "" {
req.URL.RawPath = strings.TrimSuffix(pw.With, "/") + "/" + req.URL.RawPath
}
}
if len(path.Headers) > 0 {
for _, header := range path.Headers {
//req.Header.Add(header.Name, header.Value)
value := ""
switch header.Value {
case string(model.ProxyHost):
value = turl.Host
default:
value = header.Value
}
req.Header.Set(header.Name, value)
}
} }
} }

View File

@ -1,7 +1,8 @@
package server package handler
import ( import (
"net/http" "net/http"
"net/url"
"strings" "strings"
"github.com/samber/lo" "github.com/samber/lo"
@ -10,9 +11,18 @@ import (
type ProxyRequestUpdater func(arg ...string) func(r *http.Request) type ProxyRequestUpdater func(arg ...string) func(r *http.Request)
var ProxyRequestUpdateMap = map[string]ProxyRequestUpdater{ var ProxyRequestUpdateMap = map[string]ProxyRequestUpdater{
"Host": func(arg ...string) func(r *http.Request) { "HostSchemas": func(arg ...string) func(r *http.Request) {
targetUrl := arg[0]
return func(r *http.Request) { return func(r *http.Request) {
r.Host = arg[0] turl, _ := url.Parse(targetUrl)
r.URL.Host = turl.Host
r.URL.Scheme = turl.Scheme
}
},
"HeaderOrigin": func(arg ...string) func(r *http.Request) {
return func(r *http.Request) {
r.Header.Set("Origin", r.URL.Scheme+"://"+r.URL.Host)
} }
}, },
"Path": func(arg ...string) func(r *http.Request) { "Path": func(arg ...string) func(r *http.Request) {

View File

@ -13,18 +13,7 @@ type HttpPath struct {
Root string `json:"root"` Root string `json:"root"`
Default string `json:"default"` Default string `json:"default"`
Upstreams []string `json:"upstreams"` Upstreams []string `json:"upstreams"`
Rewrite PathRewrite `json:"pathrewrite"` Directives string `json:"directives"`
Headers []HeaderDefine `json:"headers"`
}
type PathRewrite struct {
Replace string `json:"replace"`
With string `json:"with"`
}
type HeaderDefine struct {
Name string `json:"name"`
Value string `json:"value"`
} }
type HeaderValueConst string type HeaderValueConst string
@ -43,6 +32,7 @@ type HttpServerConfig struct {
Password string `json:"password"` Password string `json:"password"`
CertFile string `json:"certfile"` CertFile string `json:"certfile"`
KeyFile string `json:"keyfile"` KeyFile string `json:"keyfile"`
Directives string `json:"directives"`
} }
type GoHttpdConfig struct { type GoHttpdConfig struct {

View File

@ -7,12 +7,14 @@ type Directive func(args ...string) Middleware
var Add_Header Directive = func(args ...string) Middleware { var Add_Header Directive = func(args ...string) Middleware {
return func(w http.ResponseWriter, r *http.Request, next func()) { return func(w http.ResponseWriter, r *http.Request, next func()) {
w.Header().Add(args[0], args[1]) w.Header().Add(args[0], args[1])
next()
} }
} }
var Set_Header Directive = func(args ...string) Middleware { var Set_Header Directive = func(args ...string) Middleware {
return func(w http.ResponseWriter, r *http.Request, next func()) { return func(w http.ResponseWriter, r *http.Request, next func()) {
w.Header().Set(args[0], args[1]) w.Header().Set(args[0], args[1])
next()
} }
} }

View File

@ -7,7 +7,10 @@ import (
"sort" "sort"
"strings" "strings"
handler "git.pyer.club/kingecg/gohttpd/hander"
"git.pyer.club/kingecg/gohttpd/model"
"git.pyer.club/kingecg/gologger" "git.pyer.club/kingecg/gologger"
logger "git.pyer.club/kingecg/gologger"
) )
type RequestCtxKey string type RequestCtxKey string
@ -228,3 +231,32 @@ func (s *ServerMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
http.NotFound(w, r) http.NotFound(w, r)
} }
func NewServeMux(c *model.HttpServerConfig) *ServerMux {
l := logger.GetLogger("ServerMux")
l.Debug("NewServeMux")
s := &ServerMux{
directiveHandlers: NewMiddlewareLink(),
handlers: make(map[string]http.Handler),
paths: []string{},
}
for _, directive := range c.Directives {
s.AddDirective(string(directive))
}
for _, httpPath := range c.Paths {
if httpPath.Root != "" {
fileHandler := handler.NewFileHandler(handler.FileHandler{
Root: httpPath.Root,
Default: httpPath.Default,
})
s.Handle(httpPath.Path, fileHandler)
} else if len(httpPath.Upstreams) != 0 {
proxyHandler := handler.NewProxyHandler(&httpPath)
s.Handle(httpPath.Path, proxyHandler)
} else {
l.Error("Not supportted server path type :", httpPath.Path)
}
}
return s
}