diff --git a/README.md b/README.md index 068310582dca2c13220d11860194b506862b6506..3dcebb516423d664d502a8dd7af7b94877905ad1 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,24 @@ ## 简介 -**GoKu API Gateway CE,中文名:悟空API网关(开源版),是国内首个开源go语言API网关,帮助企业进行API服务治理、API性能安全维护,为企业数字化赋能。** +**GoKu API Gateway CE,中文名:悟空API网关(开源版),是eoLinker旗下的API网关,帮助企业进行API服务治理、API性能安全维护,为企业数字化赋能。** GoKu API Gateway CE,支持OpenAPI与微服务管理,支持私有云部署,实现API转发、请求参数转换、数据校验等功能,提供图形化界面管理,能够快速管理多个API网关,提高API业务安全性。 +## 相关链接 + +* 官方网站:https://agw.eolinker.com + +* 教程文档:http://help.eolinker.com/agw + +* 官方交流Q群:[用户交流1群](https://jq.qq.com/?_wv=1027&k=5ikfC2S)(群号:725853895) + +* Github:https://github.com/eolinker/GoKu-API-Gateway + +* 码云:https://gitee.com/eoLinker-API-Management/API-Gateway + +* Coding:https://git.coding.net/eolinker/Goku-API-Gateway.git + ## 特性 1. **免费且开源**:GoKu API Gateway秉承开源精神,是国内第一个企业开源的API接口网关,为广大的开发、运维以及管理人员提供专业的产品。 @@ -36,26 +50,18 @@ GoKu API Gateway CE,支持OpenAPI与微服务管理,支持私有云部署, ![](http://data.eolinker.com/course/pRMJNTb1974cd4d502bf17f5b477b236cf5c090496af571) +## 更新日志 -## 部署要求 - -* go 1.8及以上版本 - -## 相关链接 - -* 官方网站:https://agw.eolinker.com - -* Github:https://github.com/eolinker/GoKu-API-Gateway - -* 码云:https://gitee.com/eoLinker-API-Management/API-Gateway - -* Coding:https://git.coding.net/eolinker/Goku-API-Gateway.git +#### V2.1.4(2018/9/7) +新增: -* 教程文档:http://help.eolinker.com/agw +1. 策略ID参数支持放在Header。 -* 官方交流Q群:[用户交流1群](https://jq.qq.com/?_wv=1027&k=5ikfC2S)(群号:725853895) +说明: -## 更新日志 +通过网关访问的请求地址注意事项: +* 若策略ID放头部,则完整请求路径为:**网关IP:端口号/网关别名/接口路径**,策略ID的Header字段名为:**Strategy-Id**。 +* 若策略ID放URI,则完整请求路径为:**网关IP:端口号/网关别名/策略ID/接口路径**。 #### V2.1.3(2018/5/30) 新增: diff --git a/release/goku-ce-2.1.3.zip b/release/goku-ce-2.1.3.zip deleted file mode 100644 index 84e0fead3b96720756fd5dc4173d34f52dcd990f..0000000000000000000000000000000000000000 Binary files a/release/goku-ce-2.1.3.zip and /dev/null differ diff --git a/release/goku-ce-2.1.4.zip b/release/goku-ce-2.1.4.zip new file mode 100644 index 0000000000000000000000000000000000000000..b4a96ab1506243a4ca9bebef3a9156ca1b7469ff Binary files /dev/null and b/release/goku-ce-2.1.4.zip differ diff --git a/source_code_backend/goku-ce-admin.go b/source_code_backend/goku-ce-admin.go index 1a981e634f05b93b176b88b1151a0cf9fa07b3a2..37561b608ef443341b1c96f5ee044e7ce6b126e5 100644 --- a/source_code_backend/goku-ce-admin.go +++ b/source_code_backend/goku-ce-admin.go @@ -3,91 +3,92 @@ package main import ( "fmt" _ "goku-ce/server/conf" - "net/http" "goku-ce/server/controller" + "net/http" ) func main() { + // 游客 - http.HandleFunc("/Web/Guest/login",controller.Login) - + http.HandleFunc("/Web/Guest/login", controller.Login) + // 用户 - http.HandleFunc("/Web/User/checkLogin",controller.CheckLogin) - http.HandleFunc("/Web/User/logout",controller.Logout) + http.HandleFunc("/Web/User/checkLogin", controller.CheckLogin) + http.HandleFunc("/Web/User/logout", controller.Logout) // 网关 - http.HandleFunc("/Web/Gateway/addGateway",controller.AddGateway) - http.HandleFunc("/Web/Gateway/editGateway",controller.EditGateway) - http.HandleFunc("/Web/Gateway/deleteGateway",controller.DeleteGateway) - http.HandleFunc("/Web/Gateway/getGatewayList",controller.GetGatewayList) - http.HandleFunc("/Web/Gateway/getGateway",controller.GetGatewayInfo) - http.HandleFunc("/Web/Gateway/checkGatewayAliasIsExist",controller.CheckGatewayAliasIsExist) + http.HandleFunc("/Web/Gateway/addGateway", controller.AddGateway) + http.HandleFunc("/Web/Gateway/editGateway", controller.EditGateway) + http.HandleFunc("/Web/Gateway/deleteGateway", controller.DeleteGateway) + http.HandleFunc("/Web/Gateway/getGatewayList", controller.GetGatewayList) + http.HandleFunc("/Web/Gateway/getGateway", controller.GetGatewayInfo) + http.HandleFunc("/Web/Gateway/checkGatewayAliasIsExist", controller.CheckGatewayAliasIsExist) //网关服务 - http.HandleFunc("/Web/GatewayService/restart",controller.RestartGatewayService) - http.HandleFunc("/Web/GatewayService/reload",controller.ReloadGatewayService) - http.HandleFunc("/Web/GatewayService/stop",controller.StopGatewayService) - http.HandleFunc("/Web/GatewayService/start",controller.StartGatewayService) + http.HandleFunc("/Web/GatewayService/restart", controller.RestartGatewayService) + http.HandleFunc("/Web/GatewayService/reload", controller.ReloadGatewayService) + http.HandleFunc("/Web/GatewayService/stop", controller.StopGatewayService) + http.HandleFunc("/Web/GatewayService/start", controller.StartGatewayService) // 后端服务 - http.HandleFunc("/Web/Backend/addBackend",controller.AddBackend) - http.HandleFunc("/Web/Backend/editBackend",controller.EditBackend) - http.HandleFunc("/Web/Backend/deleteBackend",controller.DeleteBackend) - http.HandleFunc("/Web/Backend/getBackendList",controller.GetBackendList) - http.HandleFunc("/Web/Backend/getBackend",controller.GetBackendInfo) + http.HandleFunc("/Web/Backend/addBackend", controller.AddBackend) + http.HandleFunc("/Web/Backend/editBackend", controller.EditBackend) + http.HandleFunc("/Web/Backend/deleteBackend", controller.DeleteBackend) + http.HandleFunc("/Web/Backend/getBackendList", controller.GetBackendList) + http.HandleFunc("/Web/Backend/getBackend", controller.GetBackendInfo) // API分组 - http.HandleFunc("/Web/ApiGroup/addGroup",controller.AddApiGroup) - http.HandleFunc("/Web/ApiGroup/editGroup",controller.EditApiGroup) - http.HandleFunc("/Web/ApiGroup/deleteGroup",controller.DeleteApiGroup) - http.HandleFunc("/Web/ApiGroup/getGroupList",controller.GetApiGroupList) + http.HandleFunc("/Web/ApiGroup/addGroup", controller.AddApiGroup) + http.HandleFunc("/Web/ApiGroup/editGroup", controller.EditApiGroup) + http.HandleFunc("/Web/ApiGroup/deleteGroup", controller.DeleteApiGroup) + http.HandleFunc("/Web/ApiGroup/getGroupList", controller.GetApiGroupList) // API - http.HandleFunc("/Web/Api/addApi",controller.AddApi) - http.HandleFunc("/Web/Api/editApi",controller.EditApi) - http.HandleFunc("/Web/Api/deleteApi",controller.DeleteApi) - http.HandleFunc("/Web/Api/getApi",controller.GetApiInfo) - http.HandleFunc("/Web/Api/searchApi",controller.SearchApi) - http.HandleFunc("/Web/Api/getAllApiList",controller.GetAllApiList) - http.HandleFunc("/Web/Api/getApiList",controller.GetApiListByGroup) - http.HandleFunc("/Web/Api/checkApiURLIsExist",controller.CheckApiURLIsExist) + http.HandleFunc("/Web/Api/addApi", controller.AddApi) + http.HandleFunc("/Web/Api/editApi", controller.EditApi) + http.HandleFunc("/Web/Api/deleteApi", controller.DeleteApi) + http.HandleFunc("/Web/Api/getApi", controller.GetApiInfo) + http.HandleFunc("/Web/Api/searchApi", controller.SearchApi) + http.HandleFunc("/Web/Api/getAllApiList", controller.GetAllApiList) + http.HandleFunc("/Web/Api/getApiList", controller.GetApiListByGroup) + http.HandleFunc("/Web/Api/checkApiURLIsExist", controller.CheckApiURLIsExist) // 策略组 - http.HandleFunc("/Web/Strategy/addStrategy",controller.AddStrategy) - http.HandleFunc("/Web/Strategy/editStrategy",controller.EditStrategy) - http.HandleFunc("/Web/Strategy/deleteStrategy",controller.DeleteStrategy) - http.HandleFunc("/Web/Strategy/getStrategyList",controller.GetStrategyList) - http.HandleFunc("/Web/Strategy/getSimpleStrategyList",controller.GetSimpleStrategyList) + http.HandleFunc("/Web/Strategy/addStrategy", controller.AddStrategy) + http.HandleFunc("/Web/Strategy/editStrategy", controller.EditStrategy) + http.HandleFunc("/Web/Strategy/deleteStrategy", controller.DeleteStrategy) + http.HandleFunc("/Web/Strategy/getStrategyList", controller.GetStrategyList) + http.HandleFunc("/Web/Strategy/getSimpleStrategyList", controller.GetSimpleStrategyList) // 流控 - http.HandleFunc("/Web/RateLimit/addRateLimit",controller.AddRateLimit) - http.HandleFunc("/Web/RateLimit/editRateLimit",controller.EditRateLimit) - http.HandleFunc("/Web/RateLimit/deleteRateLimit",controller.DeleteRateLimit) - http.HandleFunc("/Web/RateLimit/getRateLimitInfo",controller.GetRateLimitInfo) - http.HandleFunc("/Web/RateLimit/getRateLimitList",controller.GetRateLimitList) + http.HandleFunc("/Web/RateLimit/addRateLimit", controller.AddRateLimit) + http.HandleFunc("/Web/RateLimit/editRateLimit", controller.EditRateLimit) + http.HandleFunc("/Web/RateLimit/deleteRateLimit", controller.DeleteRateLimit) + http.HandleFunc("/Web/RateLimit/getRateLimitInfo", controller.GetRateLimitInfo) + http.HandleFunc("/Web/RateLimit/getRateLimitList", controller.GetRateLimitList) // 鉴权 - http.HandleFunc("/Web/Auth/editAuth",controller.EditAuth) - http.HandleFunc("/Web/Auth/getAuthInfo",controller.GetAuthInfo) + http.HandleFunc("/Web/Auth/editAuth", controller.EditAuth) + http.HandleFunc("/Web/Auth/getAuthInfo", controller.GetAuthInfo) // 黑白名单 - http.HandleFunc("/Web/IP/editGatewayIPList",controller.EditGatewayIPList) - http.HandleFunc("/Web/IP/editStrategyIPList",controller.EditStrategyIPList) - http.HandleFunc("/Web/IP/getGatewayIPList",controller.GetGatewayIPList) - http.HandleFunc("/Web/IP/getStrategyIPList",controller.GetStrategyIPList) + http.HandleFunc("/Web/IP/editGatewayIPList", controller.EditGatewayIPList) + http.HandleFunc("/Web/IP/editStrategyIPList", controller.EditStrategyIPList) + http.HandleFunc("/Web/IP/getGatewayIPList", controller.GetGatewayIPList) + http.HandleFunc("/Web/IP/getStrategyIPList", controller.GetStrategyIPList) // 安装 - http.HandleFunc("/Web/Install/install",controller.Install) - http.HandleFunc("/Web/Install/checkIsInstall",controller.CheckIsInstall) + http.HandleFunc("/Web/Install/install", controller.Install) + http.HandleFunc("/Web/Install/checkIsInstall", controller.CheckIsInstall) // 全局配置 - http.HandleFunc("/Web/Global/getConfInfo",controller.GetGlobalConfig) - http.HandleFunc("/Web/Global/editConfInfo",controller.EditGlobalConfig) + http.HandleFunc("/Web/Global/getConfInfo", controller.GetGlobalConfig) + http.HandleFunc("/Web/Global/editConfInfo", controller.EditGlobalConfig) fmt.Println("Listen: 9900") - err := http.ListenAndServe(":9900", nil) - - if err != nil { - panic(err) - } -} \ No newline at end of file + err := http.ListenAndServe(":9900", nil) + + if err != nil { + panic(err) + } +} diff --git a/source_code_backend/goku-ce.go b/source_code_backend/goku-ce.go index ecd81209419aba104680773d131f3d0a48f86db2..af7de900f467f1589f24f4269fe0fc232bddebc0 100644 --- a/source_code_backend/goku-ce.go +++ b/source_code_backend/goku-ce.go @@ -2,23 +2,22 @@ package main import ( "fmt" - _ "goku-ce/utils" "goku-ce/goku" "goku-ce/middleware" - "os" + "goku-ce/utils" "log" + "os" ) func main() { + utils.ParseArgs() server := goku.New() - server.RegisterRouter(server.ServiceConfig,middleware.Mapping,middleware.GetVisitCount) - fmt.Println("Listen",server.ServiceConfig.Port) - err := goku.ListenAndServe(":" + server.ServiceConfig.Port,server) - if err != nil { + server.RegisterRouter(server.ServiceConfig, middleware.Mapping, middleware.GetVisitCount) + fmt.Println("Listen", server.ServiceConfig.Port) + err := goku.ListenAndServe(":"+server.ServiceConfig.Port, server) + if err != nil { log.Println(err) } log.Println("Server on " + server.ServiceConfig.Port + " stopped") os.Exit(0) } - - diff --git a/source_code_backend/goku/context.go b/source_code_backend/goku/context.go index 30594642aecfb1b6e6160ce3af0ff64e657346f9..d76a641014a93ee7c1019a29ab6eec4100db7733 100644 --- a/source_code_backend/goku/context.go +++ b/source_code_backend/goku/context.go @@ -3,41 +3,42 @@ package goku import ( "goku-ce/conf" ) + type Context struct { - GatewayInfo Gateway + GatewayInfo Gateway StrategyInfo Strategy - ApiInfo Api - Rate map[string]Rate - VisitCount *Count + ApiInfo Api + Rate map[string]Rate + VisitCount *Count } type Gateway struct { - GatewayAlias string `json:"gateway_alias" yaml:"gateway_alias"` - GatewayStatus string `json:"gateway_status" yaml:"gateway_status"` - IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` - IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` - IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` + GatewayAlias string `json:"gateway_alias" yaml:"gateway_alias"` + GatewayStatus string `json:"gateway_status" yaml:"gateway_status"` + IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` + IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` + IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` } type Strategy struct { - StrategyID string `json:"strategy_id" yaml:"strategy_id"` - Auth string `json:"auth" yaml:"auth"` - BasicUserName string `json:"basic_user_name" yaml:"basic_user_name"` - BasicUserPassword string `json:"basic_user_password" yaml:"basic_user_password"` - ApiKey string `json:"api_key" yaml:"api_key"` - IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` - IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` - IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` - RateLimitList []conf.RateLimitInfo `json:"rate_limit_list" yaml:"rate_limit_list"` + StrategyID string `json:"strategy_id" yaml:"strategy_id"` + Auth string `json:"auth" yaml:"auth"` + BasicUserName string `json:"basic_user_name" yaml:"basic_user_name"` + BasicUserPassword string `json:"basic_user_password" yaml:"basic_user_password"` + ApiKey string `json:"api_key" yaml:"api_key"` + IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` + IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` + IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` + RateLimitList []conf.RateLimitInfo `json:"rate_limit_list" yaml:"rate_limit_list"` } type Api struct { - RequestURL string `json:"request_url" yaml:"request_url"` - BackendPath string `json:"backend_path" yaml:"backend_path"` - ProxyURL string `json:"proxy_url" yaml:"proxy_url"` - ProxyMethod string `json:"proxy_method" yaml:"proxy_method"` - IsRaw bool `json:"is_raw" yaml:"is_raw"` - ProxyParams []conf.Param `json:"proxy_params" yaml:"proxy_params"` - ConstantParams []conf.ConstantParam `json:"constant_params" yaml:"constant_params"` - Follow bool `json:"follow" yaml:"follow"` + RequestURL string `json:"request_url" yaml:"request_url"` + BackendPath string `json:"backend_path" yaml:"backend_path"` + ProxyURL string `json:"proxy_url" yaml:"proxy_url"` + ProxyMethod string `json:"proxy_method" yaml:"proxy_method"` + IsRaw bool `json:"is_raw" yaml:"is_raw"` + ProxyParams []conf.Param `json:"proxy_params" yaml:"proxy_params"` + ConstantParams []conf.ConstantParam `json:"constant_params" yaml:"constant_params"` + Follow bool `json:"follow" yaml:"follow"` } diff --git a/source_code_backend/goku/router.go b/source_code_backend/goku/router.go index a39999e15c15dd605746d32e3d5b568d6e5faaa0..1b26982bde1844566bcacecee77f63bcd624a536 100644 --- a/source_code_backend/goku/router.go +++ b/source_code_backend/goku/router.go @@ -1,13 +1,15 @@ package goku import ( - "net/http" "goku-ce/conf" + "net/http" + "reflect" "strings" ) // Handle是一个可以被注册到路由中去处理http请求,类似于HandlerFunc,但是有第三个参数值 -type Handle func(http.ResponseWriter, *http.Request, Params,*Context) +type Handle func(http.ResponseWriter, *http.Request, Params, *Context) + // Param is a single URL parameter, consisting of a key and a value. type Param struct { Key string @@ -17,7 +19,12 @@ type Param struct { // Params是一个参数切片,作为路由的返回结果,这个切片是有序的 // 第一个URL参数会作为第一个切片值,因此通过索引来读值是安全的 type Params []Param -var requestMethod = []string{"POST","GET","DELETE","PUT","PATCH","OPTIONS","HEAD"} + +var requestMethod = []string{"POST", "GET", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD"} + +var strategyMap map[string]Strategy = make(map[string]Strategy) +var gatewayMap map[string]Gateway = make(map[string]Gateway) + // ByName returns the value of the first Param which key matches the given name. // If no matching Param is found, an empty string is returned. func (ps Params) ByName(name string) string { @@ -29,7 +36,7 @@ func (ps Params) ByName(name string) string { return "" } -// Router是一个可以被用来调度请求去不同处理函数的Handler +// Router是一个可以被用来调度请求去不同处理函数的Handler type Router struct { trees map[string]*node @@ -61,13 +68,11 @@ func NewRouter() *Router { } } - func (r *Router) Use(handle Handle) { r.handle = handle } - -func (r *Router) Handle(method, path string, handle Handle,context Context) { +func (r *Router) Handle(method, path string, handle Handle, context Context) { if path[0] != '/' { panic("path must begin with '/' in path '" + path + "'") } @@ -81,7 +86,7 @@ func (r *Router) Handle(method, path string, handle Handle,context Context) { root = new(node) r.trees[method] = root } - root.addRoute(path, handle,context) + root.addRoute(path, handle, context) } // // HandlerFunc 是一个适配器允许使用http.HandleFunc函数作为一个请求处理器 @@ -90,6 +95,7 @@ func (r *Router) recv(w http.ResponseWriter, req *http.Request) { r.PanicHandler(w, req, rcv) } } + // 查找允许手动查找方法 + 路径组合。 // 这对于构建围绕此路由器的框架非常有用。 // 如果找到路径, 它将返回句柄函数和路径参数值 @@ -98,7 +104,7 @@ func (r *Router) Lookup(method, path string) (Handle, Params, *Context, bool) { if root := r.trees[method]; root != nil { return root.getValue(path) } - return nil, nil,&Context{}, false + return nil, nil, &Context{}, false } func (r *Router) allowed(path, reqMethod string) (allow string) { @@ -123,7 +129,7 @@ func (r *Router) allowed(path, reqMethod string) (allow string) { continue } - handle, _, _,_ := r.trees[method].getValue(path) + handle, _, _, _ := r.trees[method].getValue(path) if handle != nil { // 将请求方法添加到允许的方法列表中 if len(allow) == 0 { @@ -143,38 +149,76 @@ func (r *Router) allowed(path, reqMethod string) (allow string) { // ServeHTTP使用路由实现http.Handler接口 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { if r.PanicHandler != nil { - + defer r.recv(w, req) } // now := time.Now() path := req.URL.Path - pathArray := strings.Split(path,"/") - - if len(pathArray) == 2 { - w.WriteHeader(500) - if pathArray[1] == "" { - w.Write([]byte("Missing Gateway Alias")) - } else { - w.Write([]byte("Missing StrategyID")) + isMatchHeader := false + + var strategy Strategy + var gateway Gateway + + // 从头部获取策略ID + strategyID := req.Header.Get("Strategy-Id") + if strategyID == "" { + // 从uri中获取策略ID + pathArray := strings.Split(path, "/") + + if len(pathArray) == 2 { + w.WriteHeader(500) + if pathArray[1] == "" { + w.Write([]byte("Missing Gateway Alias")) + } else { + w.Write([]byte("Missing StrategyID")) + } + return + } else if len(pathArray) == 3 { + w.WriteHeader(500) + if pathArray[2] == "" { + w.Write([]byte("Missing StrategyID")) + } else { + w.Write([]byte("Invalid URI")) + } + return } - return - } else if len(pathArray) == 3 { - w.WriteHeader(500) - if pathArray[2] == "" { - w.Write([]byte("Missing StrategyID")) + } else { + isMatchHeader = true + pathArray := strings.Split(path, "/") + if len(pathArray) == 2 { + w.WriteHeader(500) + if pathArray[1] == "" { + w.Write([]byte("Missing Gateway Alias")) + } + return + } + if value, ok := strategyMap[pathArray[1]+":"+strategyID]; ok { + strategy = value } else { - w.Write([]byte("Invalid URI")) + w.WriteHeader(500) + w.Write([]byte("Missing Gateway Alias or StrategyID")) + return } - return } - + if root := r.trees[req.Method]; root != nil { - handle, ps, context,tsr := root.getValue(path); + handle, ps, context, tsr := root.getValue(path) if handle != nil { - handle(w, req, ps,context) + if isMatchHeader { + context.StrategyInfo = strategy + context.GatewayInfo = gateway + } else { + st := reflect.ValueOf(context.StrategyInfo) + val := st.FieldByName("StrategyID").String() + if val == "" { + w.Write([]byte("Missing StrategyID")) + return + } + } + handle(w, req, ps, context) return } else if req.Method != "CONNECT" && path != "/" { - code := 301 + code := 301 if req.Method != "GET" { code = 307 } @@ -237,73 +281,109 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { } // 注册路由 -func (r *Router) RegisterRouter(c conf.GlobalConfig,handle ...Handle) { +func (r *Router) RegisterRouter(c conf.GlobalConfig, handle ...Handle) { r.handle = handle[0] var count = &Count{} - r.Handle("GET","/goku/Count/getVisitCount",handle[1],Context{ - VisitCount:count, + r.Handle("GET", "/goku/Count/getVisitCount", handle[1], Context{ + VisitCount: count, }) for _, g := range c.GatewayList { if g.GatewayStatus != "on" { continue } gateway := Gateway{ - GatewayAlias: g.GatewayAlias, - GatewayStatus: g.GatewayStatus, - IPLimitType: g.IPLimitType, - IPWhiteList: g.IPWhiteList, - IPBlackList: g.IPBlackList, + GatewayAlias: g.GatewayAlias, + GatewayStatus: g.GatewayStatus, + IPLimitType: g.IPLimitType, + IPWhiteList: g.IPWhiteList, + IPBlackList: g.IPBlackList, } + gatewayMap[g.GatewayAlias] = gateway for _, s := range g.StrategyList.Strategy { strategy := Strategy{ - StrategyID: s.StrategyID, - Auth: s.Auth, - ApiKey: s.ApiKey, - BasicUserName: s.BasicUserName, + StrategyID: s.StrategyID, + Auth: s.Auth, + ApiKey: s.ApiKey, + BasicUserName: s.BasicUserName, BasicUserPassword: s.BasicUserPassword, - IPLimitType: s.IPLimitType, - IPWhiteList: s.IPWhiteList, - IPBlackList: s.IPBlackList, - RateLimitList:s.RateLimitList, + IPLimitType: s.IPLimitType, + IPWhiteList: s.IPWhiteList, + IPBlackList: s.IPBlackList, + RateLimitList: s.RateLimitList, } + strategyMap[g.GatewayAlias+":"+s.StrategyID] = strategy for _, api := range g.ApiList.Apis { path := "/" + g.GatewayAlias + "/" + s.StrategyID + api.RequestURL backendPath := "" flag := false // 获取后端请求路径 - for _,b := range g.BackendList.Backend { - if b.BackendID == api.BackendID{ + for _, b := range g.BackendList.Backend { + if b.BackendID == api.BackendID { backendPath = b.BackendPath - flag =true + flag = true break } } - if !flag && api.BackendID != -1{ + if !flag && api.BackendID != -1 { continue } apiInfo := Api{ - RequestURL: api.RequestURL, - BackendPath: backendPath, - ProxyURL: api.ProxyURL, - IsRaw:api.IsRaw, - ProxyMethod:api.ProxyMethod, - ProxyParams:api.ProxyParams, - ConstantParams:api.ConstantParams, - Follow:api.Follow, + RequestURL: api.RequestURL, + BackendPath: backendPath, + ProxyURL: api.ProxyURL, + IsRaw: api.IsRaw, + ProxyMethod: api.ProxyMethod, + ProxyParams: api.ProxyParams, + ConstantParams: api.ConstantParams, + Follow: api.Follow, } context := Context{ - GatewayInfo:gateway, - StrategyInfo:strategy, - ApiInfo:apiInfo, - Rate:make(map[string]Rate), - VisitCount:count, + GatewayInfo: gateway, + StrategyInfo: strategy, + ApiInfo: apiInfo, + Rate: make(map[string]Rate), + VisitCount: count, } - - for _,method := range api.RequestMethod { - r.Handle(strings.ToUpper(method),path,r.handle,context) + for _, method := range api.RequestMethod { + r.Handle(strings.ToUpper(method), path, r.handle, context) } } } + for _, api := range g.ApiList.Apis { + path := "/" + g.GatewayAlias + api.RequestURL + backendPath := "" + flag := false + // 获取后端请求路径 + for _, b := range g.BackendList.Backend { + if b.BackendID == api.BackendID { + backendPath = b.BackendPath + flag = true + break + } + } + if !flag && api.BackendID != -1 { + continue + } + apiInfo := Api{ + RequestURL: api.RequestURL, + BackendPath: backendPath, + ProxyURL: api.ProxyURL, + IsRaw: api.IsRaw, + ProxyMethod: api.ProxyMethod, + ProxyParams: api.ProxyParams, + ConstantParams: api.ConstantParams, + Follow: api.Follow, + } + ct := Context{ + GatewayInfo: gateway, + ApiInfo: apiInfo, + Rate: make(map[string]Rate), + VisitCount: count, + } + for _, method := range api.RequestMethod { + r.Handle(strings.ToUpper(method), path, r.handle, ct) + } + } } } diff --git a/source_code_backend/server/conf/api.go b/source_code_backend/server/conf/api.go index f1cc5df7b5bbaa329a4a1f61c5a2503771aeb141..d7934961ce7e737ef19f65d14c350171aad3f3ef 100644 --- a/source_code_backend/server/conf/api.go +++ b/source_code_backend/server/conf/api.go @@ -1,63 +1,65 @@ package conf import ( - "strings" + "goku-ce/utils" "io/ioutil" - "gopkg.in/yaml.v2" "sort" + "strings" "time" + + "gopkg.in/yaml.v2" ) type Api struct { - ApiList []*ApiInfo `json:"apis" yaml:"apis"` + ApiList []*ApiInfo `json:"apis" yaml:"apis"` } type ApiInfo struct { - ApiID int `json:"apiID" yaml:"api_id"` - ApiName string `json:"apiName" yaml:"api_name"` - GroupID int `json:"groupID" yaml:"group_id"` - RequestURL string `json:"requestURL" yaml:"request_url"` - RequestMethod []string `json:"requestMethod" yaml:"request_method"` - BackendID int `json:"backendID" yaml:"backend_id"` - ProxyURL string `json:"proxyURL" yaml:"proxy_url"` - ProxyMethod string `json:"proxyMethod" yaml:"proxy_method"` - IsRaw bool `json:"isRaw" yaml:"is_raw"` - ProxyParams []*Param `json:"proxyParams" yaml:"proxy_params"` - ConstantParams []*ConstantParam `json:"constantParams" yaml:"constant_params"` - Follow bool `json:"follow" yaml:"follow"` - UpdateTime string `json:"updateTime" yaml:"update_time"` - CreateTime string `json:"createTime" yaml:"createTime"` + ApiID int `json:"apiID" yaml:"api_id"` + ApiName string `json:"apiName" yaml:"api_name"` + GroupID int `json:"groupID" yaml:"group_id"` + RequestURL string `json:"requestURL" yaml:"request_url"` + RequestMethod []string `json:"requestMethod" yaml:"request_method"` + BackendID int `json:"backendID" yaml:"backend_id"` + ProxyURL string `json:"proxyURL" yaml:"proxy_url"` + ProxyMethod string `json:"proxyMethod" yaml:"proxy_method"` + IsRaw bool `json:"isRaw" yaml:"is_raw"` + ProxyParams []*Param `json:"proxyParams" yaml:"proxy_params"` + ConstantParams []*ConstantParam `json:"constantParams" yaml:"constant_params"` + Follow bool `json:"follow" yaml:"follow"` + UpdateTime string `json:"updateTime" yaml:"update_time"` + CreateTime string `json:"createTime" yaml:"createTime"` } type Param struct { - Key string `json:"key" yaml:"key"` - KeyPosition string `json:"keyPosition" yaml:"key_position"` - NotEmpty bool `json:"notEmpty" yaml:"not_empty"` - ProxyKey string `json:"proxyKey" yaml:"proxy_key"` - ProxyKeyPosition string `json:"proxyKeyPosition" yaml:"proxy_key_position"` + Key string `json:"key" yaml:"key"` + KeyPosition string `json:"keyPosition" yaml:"key_position"` + NotEmpty bool `json:"notEmpty" yaml:"not_empty"` + ProxyKey string `json:"proxyKey" yaml:"proxy_key"` + ProxyKeyPosition string `json:"proxyKeyPosition" yaml:"proxy_key_position"` } type ConstantParam struct { - Position string `json:"position" yaml:"position"` - Key string `json:"key" yaml:"key"` - Value string `json:"value" yaml:"value"` + Position string `json:"position" yaml:"position"` + Key string `json:"key" yaml:"key"` + Value string `json:"value" yaml:"value"` } type ApiSlice []map[string]interface{} - -func (a ApiSlice) Len() int { // 重写 Len() 方法 - return len(a) + +func (a ApiSlice) Len() int { // 重写 Len() 方法 + return len(a) } -func (a ApiSlice) Swap(i, j int){ // 重写 Swap() 方法 - a[i], a[j] = a[j], a[i] +func (a ApiSlice) Swap(i, j int) { // 重写 Swap() 方法 + a[i], a[j] = a[j], a[i] } -func (a ApiSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序 +func (a ApiSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到小排序 t1, t1Err := time.Parse("2006-01-02 15:04:05", a[j]["updateTime"].(string)) t2, t2Err := time.Parse("2006-01-02 15:04:05", a[i]["updateTime"].(string)) if t1Err == nil && t2Err != nil { return true - } else if t1Err == nil && t2Err == nil{ + } else if t1Err == nil && t2Err == nil { if t1.Before(t2) { return false } else { @@ -66,62 +68,65 @@ func (a ApiSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到 } else if t1Err != nil && t2Err == nil { return false } else { - s := []string{a[i]["apiName"].(string),a[j]["apiName"].(string)} + s := []string{a[i]["apiName"].(string), a[j]["apiName"].(string)} sort.Strings(s) if s[0] == a[i]["apiName"].(string) { return false - }else { + } else { return true } } } +func init() { + utils.ParseArgs() +} + // 读入接口信息 -func ParseApiInfo(path string) ([]*ApiInfo,map[int]*ApiInfo,[]map[string]interface{},int) { +func ParseApiInfo(path string) ([]*ApiInfo, map[int]*ApiInfo, []map[string]interface{}, int) { apiInfo := make(map[int]*ApiInfo) - mapApiList := make([]map[string]interface{},0) - apiList := make([]*ApiInfo,0) + mapApiList := make([]map[string]interface{}, 0) + apiList := make([]*ApiInfo, 0) var api Api - content,err := ioutil.ReadFile(path) + content, err := ioutil.ReadFile(path) if err != nil { - return apiList,apiInfo,mapApiList,0 + return apiList, apiInfo, mapApiList, 0 } - err = yaml.Unmarshal(content,&api) + err = yaml.Unmarshal(content, &api) if err != nil { panic(err) } - if len(api.ApiList) != 0 { apiList = api.ApiList } maxID := 0 - for _,a := range api.ApiList { + for _, a := range api.ApiList { if a.ApiID > maxID { maxID = a.ApiID } } - for _,a := range api.ApiList { + for _, a := range api.ApiList { apiID := a.ApiID if apiID == 0 { - apiID = maxID + 1 + apiID = maxID + 1 } value := map[string]interface{}{ - "apiID":apiID, - "apiName":a.ApiName, - "groupID":a.GroupID, - "requestURL":a.RequestURL, - "requestMethod":strings.Join(a.RequestMethod,","), - "updateTime":a.UpdateTime, - "follow": a.Follow, + "apiID": apiID, + "apiName": a.ApiName, + "groupID": a.GroupID, + "requestURL": a.RequestURL, + "requestMethod": strings.Join(a.RequestMethod, ","), + "updateTime": a.UpdateTime, + "follow": a.Follow, } - mapApiList = append(mapApiList,value) + mapApiList = append(mapApiList, value) apiInfo[apiID] = a maxID += 1 } sort.Sort(sort.Reverse(ApiSlice(mapApiList))) - return apiList,apiInfo,mapApiList,maxID + return apiList, apiInfo, mapApiList, maxID } diff --git a/source_code_backend/server/dao/GuestDao.go b/source_code_backend/server/dao/GuestDao.go index 5fad467376657f81a4d96b18a6ed7f43c614ec6a..26c1a2ed8092ee074e188791806dd6548a14faa9 100644 --- a/source_code_backend/server/dao/GuestDao.go +++ b/source_code_backend/server/dao/GuestDao.go @@ -1,12 +1,17 @@ package dao import ( + "fmt" "goku-ce/server/conf" "goku-ce/utils" ) - + // 用户登录 -func Login(loginName, loginPassword string) (bool) { +func Login(loginName, loginPassword string) bool { + fmt.Println("conf LoginName", conf.GlobalConf.LoginName) + fmt.Println("LoginName", loginName) + fmt.Println("conf LoginPassword", conf.GlobalConf.LoginPassword) + fmt.Println("LoginPassword", loginPassword) if conf.GlobalConf.LoginName == loginName && conf.GlobalConf.LoginPassword == loginPassword { return true } else { @@ -15,10 +20,10 @@ func Login(loginName, loginPassword string) (bool) { } // 检查用户是否登录 -func CheckLogin(userToken, loginName string) (bool) { - if utils.Md5(conf.GlobalConf.LoginName + conf.GlobalConf.LoginPassword) == userToken { +func CheckLogin(userToken, loginName string) bool { + if utils.Md5(conf.GlobalConf.LoginName+conf.GlobalConf.LoginPassword) == userToken { return true } else { return false } -} \ No newline at end of file +} diff --git a/source_code_backend/utils/parse_args.go b/source_code_backend/utils/parse_args.go index 2109b0af311b5bdb67cecdbbead3aa2c2847386f..3635a688427bf49533c6ffbff97a3c68861b8ddb 100644 --- a/source_code_backend/utils/parse_args.go +++ b/source_code_backend/utils/parse_args.go @@ -1,26 +1,22 @@ package utils import ( + "flag" "fmt" "goku-ce/conf" - "flag" "log" ) -func init() { - ParseArgs() -} - var ConfFilepath string = "./config/goku.conf" var command string = "start" func ParseArgs() { - flag.StringVar(&command,"s","start","send `signal` to a master process: stop, start, restart, reload") + flag.StringVar(&command, "s", "start", "send `signal` to a master process: stop, start, restart, reload") flag.StringVar(&ConfFilepath, "c", "./config/goku.conf", "Please provide a valid configuration file path") flag.Parse() err := conf.ReadConfigure(ConfFilepath) - if err != nil && ConfFilepath != "./config/goku.conf"{ + if err != nil && ConfFilepath != "./config/goku.conf" { log.Fatalln("[error]: Not a valid configuration file, check if the file exists and the validation inside") } } @@ -28,7 +24,7 @@ func ParseArgs() { func ReloadConf() { fmt.Println(ConfFilepath) err := conf.ReadConfigure(ConfFilepath) - if err != nil && ConfFilepath != "./config/goku.conf"{ + if err != nil && ConfFilepath != "./config/goku.conf" { log.Fatalln("[error]: Not a valid configuration file, check if the file exists and the validation inside") } }