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
import (
"errors"
"net/http"
"os"
"runtime"
@ -28,6 +29,11 @@ func setConfig(w http.ResponseWriter, r *http.Request) {
return
}
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)
if err != nil {
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{})
id, ok := ctxData["id"]
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))
/// configContent, _ := json.Marshal(data)
w.WriteHeader(http.StatusOK)

View File

@ -6,7 +6,6 @@ import (
"os"
"git.pyer.club/kingecg/gohttpd/admin"
handler "git.pyer.club/kingecg/gohttpd/hander"
"git.pyer.club/kingecg/gohttpd/model"
"git.pyer.club/kingecg/gohttpd/server"
"git.pyer.club/kingecg/gohttpd/utils"
@ -22,13 +21,13 @@ func (g *GoHttp) Start() {
g.logger = gologger.GetLogger("Server")
g.logger.Info("start gohttpd")
// if g.conf != nil {
adminHandler := g.assembleServerMux(conf.Admin.Paths)
adminHandler.(*http.ServeMux).Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux))
adminHandler := server.NewServeMux(conf.Admin)
adminHandler.Handle("/api/", http.StripPrefix("/api", admin.AdminServerMux))
g.makeServer(conf.Admin, adminHandler)
for _, server := range conf.Servers {
sHandler := g.assembleServerMux(server.Paths)
g.makeServer(server, sHandler)
for _, s := range conf.Servers {
sHandler := server.NewServeMux(s)
g.makeServer(s, sHandler)
}
for _, listener := range server.ServerManager {
@ -52,25 +51,6 @@ func (g *GoHttp) makeServer(conf *model.HttpServerConfig, mux http.Handler) {
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 LoadConfig() {

View File

@ -3,7 +3,6 @@ package handler
import (
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"strings"
@ -30,39 +29,34 @@ func (p *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
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 {
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) {
turl, _ := url.Parse(upstream)
req.URL.Host = turl.Host
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)
}
for _, handler := range directiveHandlers {
handler(req)
}
}

View File

@ -1,7 +1,8 @@
package server
package handler
import (
"net/http"
"net/url"
"strings"
"github.com/samber/lo"
@ -10,9 +11,18 @@ import (
type ProxyRequestUpdater func(arg ...string) func(r *http.Request)
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) {
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) {

View File

@ -9,22 +9,11 @@ import (
)
type HttpPath struct {
Path string `json:"path"`
Root string `json:"root"`
Default string `json:"default"`
Upstreams []string `json:"upstreams"`
Rewrite PathRewrite `json:"pathrewrite"`
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"`
Path string `json:"path"`
Root string `json:"root"`
Default string `json:"default"`
Upstreams []string `json:"upstreams"`
Directives string `json:"directives"`
}
type HeaderValueConst string
@ -43,6 +32,7 @@ type HttpServerConfig struct {
Password string `json:"password"`
CertFile string `json:"certfile"`
KeyFile string `json:"keyfile"`
Directives string `json:"directives"`
}
type GoHttpdConfig struct {

View File

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

View File

@ -7,7 +7,10 @@ import (
"sort"
"strings"
handler "git.pyer.club/kingecg/gohttpd/hander"
"git.pyer.club/kingecg/gohttpd/model"
"git.pyer.club/kingecg/gologger"
logger "git.pyer.club/kingecg/gologger"
)
type RequestCtxKey string
@ -228,3 +231,32 @@ func (s *ServerMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
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
}