From 2c91cdd75b56c8bcca44a75418641c796f8917cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B0=91=E5=A5=87?= Date: Mon, 2 Aug 2021 10:43:43 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20examples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 53 +++++++++++++++++++++++++++++++- examples/run_app.go | 32 +++++++++++++++++++ src/v1/jobserver/job.go | 24 ++++++++++++--- src/v1/jobserver/job_runner.go | 36 +++++++++++++--------- src/v1/jobserver/job_schedule.go | 10 ++++-- 5 files changed, 133 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 7f2639d..e73dc2d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,55 @@ # GoSage -#### 介绍 +## 介绍 + go-sage框架,目前自用 + + + +## 参考示例 + +参考示例统一放在 ./examples 下 + + + +## Documents + +### App + +统一管理各类服务资源的处理器 + + + +#### 初始化创建示例 + +``` + +func main() { + logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) + + //log + logger := v1log.NewLog("exampleApp", logPath, nil) + + //创建一个http server + server1 := getHttpServer(logger) + + app, err := v1.NewApp( + "exampleApp", + v1.WithAppOpsLog(logger), //放入logger + v1.WithAppOpsServer(server1), //放入一个 server + ) + if err != nil { + logger.Fatal(fmt.Sprintf("new app error:%s", err)) + return + } + + err = app.Run() + if err != nil { + logger.Fatal("app running error: " + err.Error()) + } + +} +``` + + + diff --git a/examples/run_app.go b/examples/run_app.go index c373eba..97af31b 100644 --- a/examples/run_app.go +++ b/examples/run_app.go @@ -2,11 +2,14 @@ package main import ( "fmt" + "gitee.com/scottq/go-framework/src/miscs" v1 "gitee.com/scottq/go-framework/src/v1" v1http "gitee.com/scottq/go-framework/src/v1/httpserver" + v1job "gitee.com/scottq/go-framework/src/v1/jobserver" v1log "gitee.com/scottq/go-framework/src/v1/log" "os" "path/filepath" + "time" ) func main() { @@ -18,10 +21,19 @@ func main() { //创建一个http server server1 := getHttpServer(logger) + //创建 job server + job1 := getJobServer(logger) + scheduler := getJobScheduler(logger) + app, err := v1.NewApp( "exampleApp", v1.WithAppOpsLog(logger), + v1.WithAppOpsStopTimeout(time.Second*5), + v1.WithAppOpsVersion("1.0"), + v1.WithAppOpsServer(server1), //将其放入app中 + v1.WithAppOpsServer(job1), //将其放入app中 + v1.WithAppOpsServer(scheduler), //将其放入app中 ) if err != nil { logger.Fatal(fmt.Sprintf("new app error:%s", err)) @@ -48,3 +60,23 @@ func getHttpServer(logger v1log.ILog) *v1http.HttpServer { return httpServer } + +func getJobServer(logger v1log.ILog) *v1job.Job { + //创建一个job + job := v1job.NewJob("printX", func() { + logger.Info("job: " + time.Now().Format(miscs.TimeLayout)) + }) + job.SetCoNum(2) + job.AddLogger(logger) + return job +} + +func getJobScheduler(logger v1log.ILog) *v1job.JobScheduler { + job := v1job.NewJob("", func() { + logger.Info("job: " + time.Now().Format(miscs.TimeLayout)) + }) + + //创建一个scheduler + scheduler := v1job.NewJobScheduler("scheduler", time.Second*2, job) + return scheduler +} diff --git a/src/v1/jobserver/job.go b/src/v1/jobserver/job.go index 12c975f..38ffaec 100644 --- a/src/v1/jobserver/job.go +++ b/src/v1/jobserver/job.go @@ -1,12 +1,15 @@ package jobserver -import "sync" +import ( + "gitee.com/scottq/go-framework/src/v1/log" + "sync" +) type IJob interface { - Run() + Run() error } -type Task =func() +type Task = func() //job,负责单个任务的执行 type Job struct { @@ -14,8 +17,9 @@ type Job struct { coNum int64 sync.WaitGroup jobEntity Task -} + log.InvokeLog +} func NewJob(name string, f func()) *Job { return &Job{ @@ -29,15 +33,25 @@ func (j *Job) SetCoNum(num int64) { j.coNum = num } -func (j *Job) Run() { +func (j *Job) Name() string { + return j.name +} + +func (j *Job) Run() error { for i := int64(0); i < j.coNum; i++ { j.Add(1) go j.run() } j.Wait() + j.Info("job[%s] run end", j.Name()) + return nil } func (j *Job) run() { j.jobEntity() j.Done() } + +func (j *Job) Stop() error { + return nil +} diff --git a/src/v1/jobserver/job_runner.go b/src/v1/jobserver/job_runner.go index c7a2b70..9cfd1ed 100644 --- a/src/v1/jobserver/job_runner.go +++ b/src/v1/jobserver/job_runner.go @@ -1,12 +1,18 @@ package jobserver -import "sync" +import ( + "fmt" + "gitee.com/scottq/go-framework/src/v1/log" + "sync" +) //JobRunner,负责并发处理某个任务 type JobRunner struct { name string sync.WaitGroup tasks []IJob + + log.InvokeLog } func NewJobRunner(name string) *JobRunner { @@ -16,28 +22,30 @@ func NewJobRunner(name string) *JobRunner { } } -func (job *JobRunner) Name() string { - return job.name +func (rn *JobRunner) Name() string { + return rn.name } -func (job *JobRunner) AddJob(j IJob) { - job.tasks = append(job.tasks, j) +func (rn *JobRunner) AddJob(j IJob) { + rn.tasks = append(rn.tasks, j) } -func (job *JobRunner) AddExecute(name string, f func()) { +func (rn *JobRunner) AddExecute(name string, f func()) { j := NewJob(name, f) - job.tasks = append(job.tasks, j) + rn.tasks = append(rn.tasks, j) } -func (job *JobRunner) Run() { - for i := 0; i < len(job.tasks); i++ { - job.Add(1) - go job.run(job.tasks[i]) +func (rn *JobRunner) Run()error { + for i := 0; i < len(rn.tasks); i++ { + rn.Add(1) + go rn.run(rn.tasks[i]) } - job.Wait() + rn.Wait() + rn.Info(fmt.Sprintf("jobRunner[%s] run end", rn.Name())) + return nil } -func (job *JobRunner) run(j IJob) { +func (rn *JobRunner) run(j IJob) { j.Run() - job.Done() + rn.Done() } diff --git a/src/v1/jobserver/job_schedule.go b/src/v1/jobserver/job_schedule.go index 9de596b..8c7eebc 100644 --- a/src/v1/jobserver/job_schedule.go +++ b/src/v1/jobserver/job_schedule.go @@ -20,8 +20,13 @@ func NewJobScheduler(name string, interval time.Duration, f IJob) *JobScheduler } } -func (sch *JobScheduler) Run() { +func (sch *JobScheduler) Name() string { + return sch.name +} + +func (sch *JobScheduler) Run() error { sch.run() + return nil } func (sch *JobScheduler) run() { @@ -42,6 +47,7 @@ func (sch *JobScheduler) run() { } } -func (sch *JobScheduler) Stop() { +func (sch *JobScheduler) Stop() error { sch.stopCh <- 0 + return nil } -- Gitee From 1c92b4d6a1e505be650d710368cb0a7a4ae44108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B0=91=E5=A5=87?= Date: Mon, 2 Aug 2021 16:37:12 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E8=BD=AC=E5=8F=91http?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/public/index.html | 15 +++++ examples/public/products/p1.html | 16 ++++++ examples/public/products/p2.html | 16 ++++++ examples/run_app.go | 2 +- examples/run_app_stop.go | 2 +- examples/run_httpserver.go | 4 +- examples/run_httpserver_forward.go | 51 +++++++++++++++++ examples/run_httpserver_middleware.go | 2 +- examples/run_httpserver_simple.go | 2 +- examples/run_job.go | 2 +- src/v1/httpserver/http_forward.go | 69 +++++++++++++++++++++++ src/v1/httpserver/server_http.go | 37 +++++++++--- src/v1/httpserver/server_http_router.go | 52 ++++++++++++----- src/v1/log/{default_log.go => log_zap.go} | 2 +- 14 files changed, 242 insertions(+), 30 deletions(-) create mode 100644 examples/public/index.html create mode 100644 examples/public/products/p1.html create mode 100644 examples/public/products/p2.html create mode 100644 examples/run_httpserver_forward.go create mode 100644 src/v1/httpserver/http_forward.go rename src/v1/log/{default_log.go => log_zap.go} (97%) diff --git a/examples/public/index.html b/examples/public/index.html new file mode 100644 index 0000000..c2c7d39 --- /dev/null +++ b/examples/public/index.html @@ -0,0 +1,15 @@ + + + + + Default Page + + +Hello World + + + + \ No newline at end of file diff --git a/examples/public/products/p1.html b/examples/public/products/p1.html new file mode 100644 index 0000000..d231d2b --- /dev/null +++ b/examples/public/products/p1.html @@ -0,0 +1,16 @@ + + + + + 产品-One + + +

产品One介绍

+返回 + + + \ No newline at end of file diff --git a/examples/public/products/p2.html b/examples/public/products/p2.html new file mode 100644 index 0000000..abfed34 --- /dev/null +++ b/examples/public/products/p2.html @@ -0,0 +1,16 @@ + + + + + 产品-Two + + +

产品Two介绍

+返回 + + + \ No newline at end of file diff --git a/examples/run_app.go b/examples/run_app.go index 97af31b..bbd9dd6 100644 --- a/examples/run_app.go +++ b/examples/run_app.go @@ -16,7 +16,7 @@ func main() { logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) //log - logger := v1log.NewLog("exampleApp", logPath, nil) + logger := v1log.NewZapLog("exampleApp", logPath, nil) //创建一个http server server1 := getHttpServer(logger) diff --git a/examples/run_app_stop.go b/examples/run_app_stop.go index 781e9c4..fe2f317 100644 --- a/examples/run_app_stop.go +++ b/examples/run_app_stop.go @@ -14,7 +14,7 @@ import ( func main() { logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) - logger := v1log.NewLog("exampleApp", logPath, nil) + logger := v1log.NewZapLog("exampleApp", logPath, nil) server1 := getHttpServer(logger, ":8080") server2 := getHttpServer(logger, ":8083") diff --git a/examples/run_httpserver.go b/examples/run_httpserver.go index b08da4c..b5daa52 100644 --- a/examples/run_httpserver.go +++ b/examples/run_httpserver.go @@ -4,6 +4,7 @@ import ( "fmt" v1http "gitee.com/scottq/go-framework/src/v1/httpserver" v1log "gitee.com/scottq/go-framework/src/v1/log" + "net/http" "os" "path/filepath" ) @@ -12,7 +13,7 @@ func main() { name := "example" logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) - logger := v1log.NewLog(name, logPath, nil) + logger := v1log.NewZapLog(name, logPath, nil) httpServer, err := v1http.NewHttpServer("", ":8080") if err != nil { logger.Error("run http server error:%s" + err.Error()) @@ -29,6 +30,7 @@ func main() { //使用json返回 httpServer.RouteGet("/v1/users", api.Users, nil) httpServer.RouteGet("/v1/exception", api.Exception, nil) + httpServer.RouteFiles("/static", http.Dir("public")) logger.Fatal(httpServer.Run().Error()) } diff --git a/examples/run_httpserver_forward.go b/examples/run_httpserver_forward.go new file mode 100644 index 0000000..6cca39e --- /dev/null +++ b/examples/run_httpserver_forward.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + v1http "gitee.com/scottq/go-framework/src/v1/httpserver" + v1log "gitee.com/scottq/go-framework/src/v1/log" + "os" + "path/filepath" + "time" +) + +func main() { + name := "example" + logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) + + logger := v1log.NewZapLog(name, logPath, nil) + httpServer, err := v1http.NewHttpServer("", ":28080") + if err != nil { + logger.Error("run http server error:%s" + err.Error()) + return + } + //添加logger + httpServer.AddLogger(logger) + + api := &ApiHandler{} + + //注册简单的路由 + httpServer.RouteGet("/v1", api.Index, nil) + + //使用json返回 + forward := v1http.NewHttpForwardHandler("127.0.0.1:8080/v1/users", time.Second) + httpServer.RouteHandler("GET", "/v1/users/*params", forward, []v1http.Middleware{ + ForwardMiddleware, + }) + + logger.Fatal(httpServer.Run().Error()) +} + +type ApiHandler struct { +} + +//http router +func (h *ApiHandler) Index(ctx *v1http.Ctx) { + ctx.Write([]byte("Hello World")) +} + +//中间件中设置 自定义response处理器 +var ForwardMiddleware v1http.Middleware = func(ctx *v1http.Ctx, next func(*v1http.Ctx)) { + println("forward") + next(ctx) +} diff --git a/examples/run_httpserver_middleware.go b/examples/run_httpserver_middleware.go index 13d326b..ab17d3b 100644 --- a/examples/run_httpserver_middleware.go +++ b/examples/run_httpserver_middleware.go @@ -15,7 +15,7 @@ func main() { name := "example" logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) - logger := v1log.NewLog(name, logPath, nil) + logger := v1log.NewZapLog(name, logPath, nil) httpServer, err := v1http.NewHttpServer("", ":8080") if err != nil { logger.Error("run http server error:%s" + err.Error()) diff --git a/examples/run_httpserver_simple.go b/examples/run_httpserver_simple.go index a505693..fb36035 100644 --- a/examples/run_httpserver_simple.go +++ b/examples/run_httpserver_simple.go @@ -12,7 +12,7 @@ func main() { name := "example" logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) - logger := v1log.NewLog(name, logPath, nil) + logger := v1log.NewZapLog(name, logPath, nil) httpServer, err := v1http.NewHttpServer("", ":8080") if err != nil { logger.Error("run http server error:%s" + err.Error()) diff --git a/examples/run_job.go b/examples/run_job.go index 221b22d..467dd6f 100644 --- a/examples/run_job.go +++ b/examples/run_job.go @@ -11,7 +11,7 @@ import ( func main() { name := "example" logPath := fmt.Sprintf("./runtime/logs/%s.log", filepath.Base(os.Args[0])) - logger := v1log.NewLog(name, logPath, nil) + logger := v1log.NewZapLog(name, logPath, nil) job := v1job.NewJob("printX", func() { for i := 0; i <= 10; i++ { diff --git a/src/v1/httpserver/http_forward.go b/src/v1/httpserver/http_forward.go new file mode 100644 index 0000000..f66803b --- /dev/null +++ b/src/v1/httpserver/http_forward.go @@ -0,0 +1,69 @@ +package httpserver + +import ( + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" +) + +//转发http的handler +type HttpForwardHandler struct { + forwardAddr string + client http.Client +} + +func NewHttpForwardHandler(forward string, timeout time.Duration) *HttpForwardHandler { + if !strings.HasPrefix(forward, "http") { + forward = "http://" + forward + } + return &HttpForwardHandler{ + forwardAddr: forward, + client: http.Client{Timeout: timeout,}, + } +} + +func (h *HttpForwardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + + forwardReq, err := h.copyReq(r) + if err != nil { + panic(err) + } + + httpResp, err := h.client.Do(forwardReq) + if err != nil { + panic(err) + } + defer httpResp.Body.Close() + repBody, err := ioutil.ReadAll(httpResp.Body) + if err != nil { + panic(err) + } + + w.WriteHeader(httpResp.StatusCode) + w.Write(repBody) +} + +func (h *HttpForwardHandler) copyReq(request *http.Request) (*http.Request, error) { + forwardUrl, err := url.Parse(h.forwardAddr) + if err != nil { + return nil, err + } + + request.ParseForm() + forwardUrl.RawQuery = request.Form.Encode() + + forwardMethod := request.Method + + forwardReq, err := http.NewRequest(forwardMethod, forwardUrl.String(), request.Body) + + if err != nil { + return nil, err + } + + for headerKey := range request.Header { + forwardReq.Header.Add(headerKey, request.Header.Get(headerKey)) + } + return forwardReq, nil +} diff --git a/src/v1/httpserver/server_http.go b/src/v1/httpserver/server_http.go index dab6796..e6f6854 100644 --- a/src/v1/httpserver/server_http.go +++ b/src/v1/httpserver/server_http.go @@ -33,24 +33,36 @@ func NewHttpServer(name string, addr string) (*HttpServer, error) { return server, nil } +func (s *HttpServer) Router() *httprouter.Router { + return s.rHandler +} +func (s *HttpServer) RouteFiles(path string, f http.FileSystem) *HttpServer { + s.rHandler.ServeFiles(path+"/*filepath", f) + return s +} +func (s *HttpServer) RouteHandler(method, path string, f http.Handler, middleware []Middleware) *HttpServer { + s.addRouteHandler(method, path, f, middleware) + return s +} + func (s *HttpServer) RoutePost(path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { - s.addRouter(path, "post", f, middleware) + s.addRoute("post", path, f, middleware) return s } func (s *HttpServer) RouteGet(path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { - s.addRouter(path, "get", f, middleware) + s.addRoute("get", path, f, middleware) return s } func (s *HttpServer) RouteOptions(path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { - s.addRouter(path, "options", f, middleware) + s.addRoute("options", path, f, middleware) return s } func (s *HttpServer) RouteDelete(path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { - s.addRouter(path, "delete", f, middleware) + s.addRoute("delete", path, f, middleware) return s } func (s *HttpServer) RoutePut(path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { - s.addRouter(path, "put", f, middleware) + s.addRoute("put", path, f, middleware) return s } @@ -60,12 +72,12 @@ func (s *HttpServer) DefaultRouteHealth() *HttpServer { ctx.Write([]byte("ok")) } - s.addRouter(HealthUrl, "get", healthF, nil) - s.addRouter(HealthUrl, "post", healthF, nil) + s.addRoute("get", HealthUrl, healthF, nil) + s.addRoute("post", HealthUrl, healthF, nil) return s } -func (s *HttpServer) addRouter(path, method string, f HttpRouteFunc, middleware []Middleware) *HttpServer { +func (s *HttpServer) addRoute(method, path string, f HttpRouteFunc, middleware []Middleware) *HttpServer { s.routers = append(s.routers, &Router{ Path: path, Method: method, @@ -74,6 +86,15 @@ func (s *HttpServer) addRouter(path, method string, f HttpRouteFunc, middleware }) return s } +func (s *HttpServer) addRouteHandler(method, path string, f http.Handler, middleware []Middleware) *HttpServer { + s.routers = append(s.routers, &Router{ + Path: path, + Method: method, + HttpHandler: f, + Middleware: middleware, + }) + return s +} func (s *HttpServer) initRouter() error { diff --git a/src/v1/httpserver/server_http_router.go b/src/v1/httpserver/server_http_router.go index 548153e..3abe2b5 100644 --- a/src/v1/httpserver/server_http_router.go +++ b/src/v1/httpserver/server_http_router.go @@ -11,6 +11,8 @@ type Router struct { Method string RouteHandler HttpRouteFunc Middleware []Middleware + + HttpHandler http.Handler } func (r *Router) hash() string { @@ -18,27 +20,47 @@ func (r *Router) hash() string { } func (r *Router) invokeRegister(router *httprouter.Router) { - switch strings.ToUpper(r.Method) { - case "GET": - router.GET(r.Path, r.handler()) - case "POST": - router.POST(r.Path, r.handler()) - case "OPTIONS": - router.OPTIONS(r.Path, r.handler()) - case "DELETE": - router.DELETE(r.Path, r.handler()) - case "PUT": - router.PUT(r.Path, r.handler()) + handler := r.handler() + if handler != nil { + switch strings.ToUpper(r.Method) { + case "GET": + router.GET(r.Path, handler) + case "POST": + router.POST(r.Path, handler) + case "OPTIONS": + router.OPTIONS(r.Path, handler) + case "DELETE": + router.DELETE(r.Path, handler) + case "PUT": + router.PUT(r.Path, handler) + } } } func (r *Router) handler() func(http.ResponseWriter, *http.Request, httprouter.Params) { - return func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) { - ctx := NewCtx(writer, request) - ctx._setRouterParams(params) - handlerMiddleware(r.RouteHandler,r.Middleware)(ctx) + if r.HttpHandler != nil { + return func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) { + + ctx := NewCtx(writer, request) + ctx._setRouterParams(params) + + handlerMiddleware(func(ctx *Ctx) { + r.HttpHandler.ServeHTTP(writer, request) + }, r.Middleware)(ctx) + } } + + if r.RouteHandler != nil { + return func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) { + ctx := NewCtx(writer, request) + ctx._setRouterParams(params) + + handlerMiddleware(r.RouteHandler, r.Middleware)(ctx) + } + } + + return nil } type HttpRouteFunc = func(ctx *Ctx) diff --git a/src/v1/log/default_log.go b/src/v1/log/log_zap.go similarity index 97% rename from src/v1/log/default_log.go rename to src/v1/log/log_zap.go index 42bcb5b..e3b25d7 100644 --- a/src/v1/log/default_log.go +++ b/src/v1/log/log_zap.go @@ -23,7 +23,7 @@ type LogConfig struct { DebugLevel string } -func NewLog(name string, logPath string, config *LogConfig) ILog { +func NewZapLog(name string, logPath string, config *LogConfig) ILog { if config == nil { config = &LogConfig{ MaxSize: 128, // 每个日志文件保存的大小 单位:M -- Gitee From fb105bd96849ae4422956d3cfd209b9366a7a0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=B0=91=E5=A5=87?= Date: Mon, 2 Aug 2021 17:18:20 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20http=E8=BD=AC=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/run_httpserver_forward.go | 15 +++++++-- src/v1/httpserver/http_forward.go | 49 +++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/examples/run_httpserver_forward.go b/examples/run_httpserver_forward.go index 6cca39e..c0caef5 100644 --- a/examples/run_httpserver_forward.go +++ b/examples/run_httpserver_forward.go @@ -28,8 +28,17 @@ func main() { httpServer.RouteGet("/v1", api.Index, nil) //使用json返回 - forward := v1http.NewHttpForwardHandler("127.0.0.1:8080/v1/users", time.Second) - httpServer.RouteHandler("GET", "/v1/users/*params", forward, []v1http.Middleware{ + httpForward := v1http.NewHttpForwardHandler("127.0.0.1:8080/v1/users", time.Second) + httpForward.AddForwardRule(map[string]string{ + "/v2/users/*": "127.0.0.1:28080/v1/users", + "/v2/self": "127.0.0.1:28080/v1", + "/v2/file/*/index.html": "127.0.0.1:8080/static", + }) + + httpServer.RouteHandler("GET", "/v1/users/:uid", httpForward, []v1http.Middleware{ + ForwardMiddleware, + }) + httpServer.RouteHandler("GET", "/v2/*path", httpForward, []v1http.Middleware{ ForwardMiddleware, }) @@ -46,6 +55,6 @@ func (h *ApiHandler) Index(ctx *v1http.Ctx) { //中间件中设置 自定义response处理器 var ForwardMiddleware v1http.Middleware = func(ctx *v1http.Ctx, next func(*v1http.Ctx)) { - println("forward") next(ctx) + ctx.Write([]byte("\nforward: " + ctx.Param("uid"))) } diff --git a/src/v1/httpserver/http_forward.go b/src/v1/httpserver/http_forward.go index f66803b..9aa8b59 100644 --- a/src/v1/httpserver/http_forward.go +++ b/src/v1/httpserver/http_forward.go @@ -10,8 +10,9 @@ import ( //转发http的handler type HttpForwardHandler struct { - forwardAddr string - client http.Client + forwardAddr string + forwardRules map[string]string + client http.Client } func NewHttpForwardHandler(forward string, timeout time.Duration) *HttpForwardHandler { @@ -19,11 +20,21 @@ func NewHttpForwardHandler(forward string, timeout time.Duration) *HttpForwardHa forward = "http://" + forward } return &HttpForwardHandler{ - forwardAddr: forward, - client: http.Client{Timeout: timeout,}, + forwardAddr: forward, + forwardRules: map[string]string{}, + client: http.Client{Timeout: timeout,}, } } +func (h *HttpForwardHandler) AddForwardRule(rule map[string]string) { + rules := h.forwardRules + for path, forwardAddr := range rule { + rules[path] = forwardAddr + } + + h.forwardRules = rules +} + func (h *HttpForwardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { forwardReq, err := h.copyReq(r) @@ -44,9 +55,35 @@ func (h *HttpForwardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.WriteHeader(httpResp.StatusCode) w.Write(repBody) } +func (h *HttpForwardHandler) getForwardAddr(request *http.Request) string { + uri := request.RequestURI + forwardAddr := h.forwardAddr + for path, addr := range h.forwardRules { + if path == uri { + forwardAddr = addr + } + + if pos := strings.Index(path, "*"); pos >= 0 { + prefix := path[:pos] + suffix := path[pos+1:] + if strings.HasPrefix(uri, prefix) && strings.HasSuffix(uri, suffix) { + forwardAddr = addr + } + } + } + if !strings.HasPrefix(forwardAddr, "http") { + forwardAddr = "http://" + forwardAddr + } + + return forwardAddr +} func (h *HttpForwardHandler) copyReq(request *http.Request) (*http.Request, error) { - forwardUrl, err := url.Parse(h.forwardAddr) + // + forwardAddr := h.getForwardAddr(request) + + // + forwardUrl, err := url.Parse(forwardAddr) if err != nil { return nil, err } @@ -65,5 +102,7 @@ func (h *HttpForwardHandler) copyReq(request *http.Request) (*http.Request, erro for headerKey := range request.Header { forwardReq.Header.Add(headerKey, request.Header.Get(headerKey)) } + + forwardReq.Header.Add("ForwardSource", request.RequestURI) return forwardReq, nil } -- Gitee