提交 d73f4c50 编写于 作者: E eoLinker API Management

'V2.1.4'

上级 c05f2fc9
...@@ -4,10 +4,24 @@ ...@@ -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业务安全性。 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接口网关,为广大的开发、运维以及管理人员提供专业的产品。 1. **免费且开源**:GoKu API Gateway秉承开源精神,是国内第一个企业开源的API接口网关,为广大的开发、运维以及管理人员提供专业的产品。
...@@ -36,26 +50,18 @@ GoKu API Gateway CE,支持OpenAPI与微服务管理,支持私有云部署, ...@@ -36,26 +50,18 @@ GoKu API Gateway CE,支持OpenAPI与微服务管理,支持私有云部署,
![](http://data.eolinker.com/course/pRMJNTb1974cd4d502bf17f5b477b236cf5c090496af571) ![](http://data.eolinker.com/course/pRMJNTb1974cd4d502bf17f5b477b236cf5c090496af571)
## 更新日志
## 部署要求 #### V2.1.4(2018/9/7)
新增:
* 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
* 教程文档: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) #### V2.1.3(2018/5/30)
新增: 新增:
......
...@@ -3,91 +3,92 @@ package main ...@@ -3,91 +3,92 @@ package main
import ( import (
"fmt" "fmt"
_ "goku-ce/server/conf" _ "goku-ce/server/conf"
"net/http"
"goku-ce/server/controller" "goku-ce/server/controller"
"net/http"
) )
func main() { 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/checkLogin", controller.CheckLogin)
http.HandleFunc("/Web/User/logout",controller.Logout) http.HandleFunc("/Web/User/logout", controller.Logout)
// 网关 // 网关
http.HandleFunc("/Web/Gateway/addGateway",controller.AddGateway) http.HandleFunc("/Web/Gateway/addGateway", controller.AddGateway)
http.HandleFunc("/Web/Gateway/editGateway",controller.EditGateway) http.HandleFunc("/Web/Gateway/editGateway", controller.EditGateway)
http.HandleFunc("/Web/Gateway/deleteGateway",controller.DeleteGateway) http.HandleFunc("/Web/Gateway/deleteGateway", controller.DeleteGateway)
http.HandleFunc("/Web/Gateway/getGatewayList",controller.GetGatewayList) http.HandleFunc("/Web/Gateway/getGatewayList", controller.GetGatewayList)
http.HandleFunc("/Web/Gateway/getGateway",controller.GetGatewayInfo) http.HandleFunc("/Web/Gateway/getGateway", controller.GetGatewayInfo)
http.HandleFunc("/Web/Gateway/checkGatewayAliasIsExist",controller.CheckGatewayAliasIsExist) http.HandleFunc("/Web/Gateway/checkGatewayAliasIsExist", controller.CheckGatewayAliasIsExist)
//网关服务 //网关服务
http.HandleFunc("/Web/GatewayService/restart",controller.RestartGatewayService) http.HandleFunc("/Web/GatewayService/restart", controller.RestartGatewayService)
http.HandleFunc("/Web/GatewayService/reload",controller.ReloadGatewayService) http.HandleFunc("/Web/GatewayService/reload", controller.ReloadGatewayService)
http.HandleFunc("/Web/GatewayService/stop",controller.StopGatewayService) http.HandleFunc("/Web/GatewayService/stop", controller.StopGatewayService)
http.HandleFunc("/Web/GatewayService/start",controller.StartGatewayService) http.HandleFunc("/Web/GatewayService/start", controller.StartGatewayService)
// 后端服务 // 后端服务
http.HandleFunc("/Web/Backend/addBackend",controller.AddBackend) http.HandleFunc("/Web/Backend/addBackend", controller.AddBackend)
http.HandleFunc("/Web/Backend/editBackend",controller.EditBackend) http.HandleFunc("/Web/Backend/editBackend", controller.EditBackend)
http.HandleFunc("/Web/Backend/deleteBackend",controller.DeleteBackend) http.HandleFunc("/Web/Backend/deleteBackend", controller.DeleteBackend)
http.HandleFunc("/Web/Backend/getBackendList",controller.GetBackendList) http.HandleFunc("/Web/Backend/getBackendList", controller.GetBackendList)
http.HandleFunc("/Web/Backend/getBackend",controller.GetBackendInfo) http.HandleFunc("/Web/Backend/getBackend", controller.GetBackendInfo)
// API分组 // API分组
http.HandleFunc("/Web/ApiGroup/addGroup",controller.AddApiGroup) http.HandleFunc("/Web/ApiGroup/addGroup", controller.AddApiGroup)
http.HandleFunc("/Web/ApiGroup/editGroup",controller.EditApiGroup) http.HandleFunc("/Web/ApiGroup/editGroup", controller.EditApiGroup)
http.HandleFunc("/Web/ApiGroup/deleteGroup",controller.DeleteApiGroup) http.HandleFunc("/Web/ApiGroup/deleteGroup", controller.DeleteApiGroup)
http.HandleFunc("/Web/ApiGroup/getGroupList",controller.GetApiGroupList) http.HandleFunc("/Web/ApiGroup/getGroupList", controller.GetApiGroupList)
// API // API
http.HandleFunc("/Web/Api/addApi",controller.AddApi) http.HandleFunc("/Web/Api/addApi", controller.AddApi)
http.HandleFunc("/Web/Api/editApi",controller.EditApi) http.HandleFunc("/Web/Api/editApi", controller.EditApi)
http.HandleFunc("/Web/Api/deleteApi",controller.DeleteApi) http.HandleFunc("/Web/Api/deleteApi", controller.DeleteApi)
http.HandleFunc("/Web/Api/getApi",controller.GetApiInfo) http.HandleFunc("/Web/Api/getApi", controller.GetApiInfo)
http.HandleFunc("/Web/Api/searchApi",controller.SearchApi) http.HandleFunc("/Web/Api/searchApi", controller.SearchApi)
http.HandleFunc("/Web/Api/getAllApiList",controller.GetAllApiList) http.HandleFunc("/Web/Api/getAllApiList", controller.GetAllApiList)
http.HandleFunc("/Web/Api/getApiList",controller.GetApiListByGroup) http.HandleFunc("/Web/Api/getApiList", controller.GetApiListByGroup)
http.HandleFunc("/Web/Api/checkApiURLIsExist",controller.CheckApiURLIsExist) http.HandleFunc("/Web/Api/checkApiURLIsExist", controller.CheckApiURLIsExist)
// 策略组 // 策略组
http.HandleFunc("/Web/Strategy/addStrategy",controller.AddStrategy) http.HandleFunc("/Web/Strategy/addStrategy", controller.AddStrategy)
http.HandleFunc("/Web/Strategy/editStrategy",controller.EditStrategy) http.HandleFunc("/Web/Strategy/editStrategy", controller.EditStrategy)
http.HandleFunc("/Web/Strategy/deleteStrategy",controller.DeleteStrategy) http.HandleFunc("/Web/Strategy/deleteStrategy", controller.DeleteStrategy)
http.HandleFunc("/Web/Strategy/getStrategyList",controller.GetStrategyList) http.HandleFunc("/Web/Strategy/getStrategyList", controller.GetStrategyList)
http.HandleFunc("/Web/Strategy/getSimpleStrategyList",controller.GetSimpleStrategyList) http.HandleFunc("/Web/Strategy/getSimpleStrategyList", controller.GetSimpleStrategyList)
// 流控 // 流控
http.HandleFunc("/Web/RateLimit/addRateLimit",controller.AddRateLimit) http.HandleFunc("/Web/RateLimit/addRateLimit", controller.AddRateLimit)
http.HandleFunc("/Web/RateLimit/editRateLimit",controller.EditRateLimit) http.HandleFunc("/Web/RateLimit/editRateLimit", controller.EditRateLimit)
http.HandleFunc("/Web/RateLimit/deleteRateLimit",controller.DeleteRateLimit) http.HandleFunc("/Web/RateLimit/deleteRateLimit", controller.DeleteRateLimit)
http.HandleFunc("/Web/RateLimit/getRateLimitInfo",controller.GetRateLimitInfo) http.HandleFunc("/Web/RateLimit/getRateLimitInfo", controller.GetRateLimitInfo)
http.HandleFunc("/Web/RateLimit/getRateLimitList",controller.GetRateLimitList) http.HandleFunc("/Web/RateLimit/getRateLimitList", controller.GetRateLimitList)
// 鉴权 // 鉴权
http.HandleFunc("/Web/Auth/editAuth",controller.EditAuth) http.HandleFunc("/Web/Auth/editAuth", controller.EditAuth)
http.HandleFunc("/Web/Auth/getAuthInfo",controller.GetAuthInfo) http.HandleFunc("/Web/Auth/getAuthInfo", controller.GetAuthInfo)
// 黑白名单 // 黑白名单
http.HandleFunc("/Web/IP/editGatewayIPList",controller.EditGatewayIPList) http.HandleFunc("/Web/IP/editGatewayIPList", controller.EditGatewayIPList)
http.HandleFunc("/Web/IP/editStrategyIPList",controller.EditStrategyIPList) http.HandleFunc("/Web/IP/editStrategyIPList", controller.EditStrategyIPList)
http.HandleFunc("/Web/IP/getGatewayIPList",controller.GetGatewayIPList) http.HandleFunc("/Web/IP/getGatewayIPList", controller.GetGatewayIPList)
http.HandleFunc("/Web/IP/getStrategyIPList",controller.GetStrategyIPList) http.HandleFunc("/Web/IP/getStrategyIPList", controller.GetStrategyIPList)
// 安装 // 安装
http.HandleFunc("/Web/Install/install",controller.Install) http.HandleFunc("/Web/Install/install", controller.Install)
http.HandleFunc("/Web/Install/checkIsInstall",controller.CheckIsInstall) http.HandleFunc("/Web/Install/checkIsInstall", controller.CheckIsInstall)
// 全局配置 // 全局配置
http.HandleFunc("/Web/Global/getConfInfo",controller.GetGlobalConfig) http.HandleFunc("/Web/Global/getConfInfo", controller.GetGlobalConfig)
http.HandleFunc("/Web/Global/editConfInfo",controller.EditGlobalConfig) http.HandleFunc("/Web/Global/editConfInfo", controller.EditGlobalConfig)
fmt.Println("Listen: 9900") fmt.Println("Listen: 9900")
err := http.ListenAndServe(":9900", nil) err := http.ListenAndServe(":9900", nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
\ No newline at end of file
...@@ -2,23 +2,22 @@ package main ...@@ -2,23 +2,22 @@ package main
import ( import (
"fmt" "fmt"
_ "goku-ce/utils"
"goku-ce/goku" "goku-ce/goku"
"goku-ce/middleware" "goku-ce/middleware"
"os" "goku-ce/utils"
"log" "log"
"os"
) )
func main() { func main() {
utils.ParseArgs()
server := goku.New() server := goku.New()
server.RegisterRouter(server.ServiceConfig,middleware.Mapping,middleware.GetVisitCount) server.RegisterRouter(server.ServiceConfig, middleware.Mapping, middleware.GetVisitCount)
fmt.Println("Listen",server.ServiceConfig.Port) fmt.Println("Listen", server.ServiceConfig.Port)
err := goku.ListenAndServe(":" + server.ServiceConfig.Port,server) err := goku.ListenAndServe(":"+server.ServiceConfig.Port, server)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
log.Println("Server on " + server.ServiceConfig.Port + " stopped") log.Println("Server on " + server.ServiceConfig.Port + " stopped")
os.Exit(0) os.Exit(0)
} }
...@@ -3,41 +3,42 @@ package goku ...@@ -3,41 +3,42 @@ package goku
import ( import (
"goku-ce/conf" "goku-ce/conf"
) )
type Context struct { type Context struct {
GatewayInfo Gateway GatewayInfo Gateway
StrategyInfo Strategy StrategyInfo Strategy
ApiInfo Api ApiInfo Api
Rate map[string]Rate Rate map[string]Rate
VisitCount *Count VisitCount *Count
} }
type Gateway struct { type Gateway struct {
GatewayAlias string `json:"gateway_alias" yaml:"gateway_alias"` GatewayAlias string `json:"gateway_alias" yaml:"gateway_alias"`
GatewayStatus string `json:"gateway_status" yaml:"gateway_status"` GatewayStatus string `json:"gateway_status" yaml:"gateway_status"`
IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"`
IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"`
IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"`
} }
type Strategy struct { type Strategy struct {
StrategyID string `json:"strategy_id" yaml:"strategy_id"` StrategyID string `json:"strategy_id" yaml:"strategy_id"`
Auth string `json:"auth" yaml:"auth"` Auth string `json:"auth" yaml:"auth"`
BasicUserName string `json:"basic_user_name" yaml:"basic_user_name"` BasicUserName string `json:"basic_user_name" yaml:"basic_user_name"`
BasicUserPassword string `json:"basic_user_password" yaml:"basic_user_password"` BasicUserPassword string `json:"basic_user_password" yaml:"basic_user_password"`
ApiKey string `json:"api_key" yaml:"api_key"` ApiKey string `json:"api_key" yaml:"api_key"`
IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"` IPLimitType string `json:"ip_limit_type" yaml:"ip_limit_type"`
IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"` IPWhiteList []string `json:"ip_white_list" yaml:"ip_white_list"`
IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"` IPBlackList []string `json:"ip_black_list" yaml:"ip_black_list"`
RateLimitList []conf.RateLimitInfo `json:"rate_limit_list" yaml:"rate_limit_list"` RateLimitList []conf.RateLimitInfo `json:"rate_limit_list" yaml:"rate_limit_list"`
} }
type Api struct { type Api struct {
RequestURL string `json:"request_url" yaml:"request_url"` RequestURL string `json:"request_url" yaml:"request_url"`
BackendPath string `json:"backend_path" yaml:"backend_path"` BackendPath string `json:"backend_path" yaml:"backend_path"`
ProxyURL string `json:"proxy_url" yaml:"proxy_url"` ProxyURL string `json:"proxy_url" yaml:"proxy_url"`
ProxyMethod string `json:"proxy_method" yaml:"proxy_method"` ProxyMethod string `json:"proxy_method" yaml:"proxy_method"`
IsRaw bool `json:"is_raw" yaml:"is_raw"` IsRaw bool `json:"is_raw" yaml:"is_raw"`
ProxyParams []conf.Param `json:"proxy_params" yaml:"proxy_params"` ProxyParams []conf.Param `json:"proxy_params" yaml:"proxy_params"`
ConstantParams []conf.ConstantParam `json:"constant_params" yaml:"constant_params"` ConstantParams []conf.ConstantParam `json:"constant_params" yaml:"constant_params"`
Follow bool `json:"follow" yaml:"follow"` Follow bool `json:"follow" yaml:"follow"`
} }
package goku package goku
import ( import (
"net/http"
"goku-ce/conf" "goku-ce/conf"
"net/http"
"reflect"
"strings" "strings"
) )
// Handle是一个可以被注册到路由中去处理http请求,类似于HandlerFunc,但是有第三个参数值 // 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. // Param is a single URL parameter, consisting of a key and a value.
type Param struct { type Param struct {
Key string Key string
...@@ -17,7 +19,12 @@ type Param struct { ...@@ -17,7 +19,12 @@ type Param struct {
// Params是一个参数切片,作为路由的返回结果,这个切片是有序的 // Params是一个参数切片,作为路由的返回结果,这个切片是有序的
// 第一个URL参数会作为第一个切片值,因此通过索引来读值是安全的 // 第一个URL参数会作为第一个切片值,因此通过索引来读值是安全的
type Params []Param 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. // 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. // If no matching Param is found, an empty string is returned.
func (ps Params) ByName(name string) string { func (ps Params) ByName(name string) string {
...@@ -29,7 +36,7 @@ func (ps Params) ByName(name string) string { ...@@ -29,7 +36,7 @@ func (ps Params) ByName(name string) string {
return "" return ""
} }
// Router是一个可以被用来调度请求去不同处理函数的Handler // Router是一个可以被用来调度请求去不同处理函数的Handler
type Router struct { type Router struct {
trees map[string]*node trees map[string]*node
...@@ -61,13 +68,11 @@ func NewRouter() *Router { ...@@ -61,13 +68,11 @@ func NewRouter() *Router {
} }
} }
func (r *Router) Use(handle Handle) { func (r *Router) Use(handle Handle) {
r.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] != '/' { if path[0] != '/' {
panic("path must begin with '/' in path '" + path + "'") panic("path must begin with '/' in path '" + path + "'")
} }
...@@ -81,7 +86,7 @@ func (r *Router) Handle(method, path string, handle Handle,context Context) { ...@@ -81,7 +86,7 @@ func (r *Router) Handle(method, path string, handle Handle,context Context) {
root = new(node) root = new(node)
r.trees[method] = root r.trees[method] = root
} }
root.addRoute(path, handle,context) root.addRoute(path, handle, context)
} }
// // HandlerFunc 是一个适配器允许使用http.HandleFunc函数作为一个请求处理器 // // HandlerFunc 是一个适配器允许使用http.HandleFunc函数作为一个请求处理器
...@@ -90,6 +95,7 @@ func (r *Router) recv(w http.ResponseWriter, req *http.Request) { ...@@ -90,6 +95,7 @@ func (r *Router) recv(w http.ResponseWriter, req *http.Request) {
r.PanicHandler(w, req, rcv) r.PanicHandler(w, req, rcv)
} }
} }
// 查找允许手动查找方法 + 路径组合。 // 查找允许手动查找方法 + 路径组合。
// 这对于构建围绕此路由器的框架非常有用。 // 这对于构建围绕此路由器的框架非常有用。
// 如果找到路径, 它将返回句柄函数和路径参数值 // 如果找到路径, 它将返回句柄函数和路径参数值
...@@ -98,7 +104,7 @@ func (r *Router) Lookup(method, path string) (Handle, Params, *Context, bool) { ...@@ -98,7 +104,7 @@ func (r *Router) Lookup(method, path string) (Handle, Params, *Context, bool) {
if root := r.trees[method]; root != nil { if root := r.trees[method]; root != nil {
return root.getValue(path) return root.getValue(path)
} }
return nil, nil,&Context{}, false return nil, nil, &Context{}, false
} }
func (r *Router) allowed(path, reqMethod string) (allow string) { func (r *Router) allowed(path, reqMethod string) (allow string) {
...@@ -123,7 +129,7 @@ func (r *Router) allowed(path, reqMethod string) (allow string) { ...@@ -123,7 +129,7 @@ func (r *Router) allowed(path, reqMethod string) (allow string) {
continue continue
} }
handle, _, _,_ := r.trees[method].getValue(path) handle, _, _, _ := r.trees[method].getValue(path)
if handle != nil { if handle != nil {
// 将请求方法添加到允许的方法列表中 // 将请求方法添加到允许的方法列表中
if len(allow) == 0 { if len(allow) == 0 {
...@@ -143,38 +149,76 @@ func (r *Router) allowed(path, reqMethod string) (allow string) { ...@@ -143,38 +149,76 @@ func (r *Router) allowed(path, reqMethod string) (allow string) {
// ServeHTTP使用路由实现http.Handler接口 // ServeHTTP使用路由实现http.Handler接口
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if r.PanicHandler != nil { if r.PanicHandler != nil {
defer r.recv(w, req) defer r.recv(w, req)
} }
// now := time.Now() // now := time.Now()
path := req.URL.Path path := req.URL.Path
pathArray := strings.Split(path,"/") isMatchHeader := false
if len(pathArray) == 2 { var strategy Strategy
w.WriteHeader(500) var gateway Gateway
if pathArray[1] == "" {
w.Write([]byte("Missing Gateway Alias")) // 从头部获取策略ID
} else { strategyID := req.Header.Get("Strategy-Id")
w.Write([]byte("Missing StrategyID")) 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 {
} else if len(pathArray) == 3 { isMatchHeader = true
w.WriteHeader(500) pathArray := strings.Split(path, "/")
if pathArray[2] == "" { if len(pathArray) == 2 {
w.Write([]byte("Missing StrategyID")) w.WriteHeader(500)
if pathArray[1] == "" {
w.Write([]byte("Missing Gateway Alias"))
}
return
}
if value, ok := strategyMap[pathArray[1]+":"+strategyID]; ok {
strategy = value
} else { } 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 { 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 { 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 return
} else if req.Method != "CONNECT" && path != "/" { } else if req.Method != "CONNECT" && path != "/" {
code := 301 code := 301
if req.Method != "GET" { if req.Method != "GET" {
code = 307 code = 307
} }
...@@ -237,73 +281,109 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { ...@@ -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] r.handle = handle[0]
var count = &Count{} var count = &Count{}
r.Handle("GET","/goku/Count/getVisitCount",handle[1],Context{ r.Handle("GET", "/goku/Count/getVisitCount", handle[1], Context{
VisitCount:count, VisitCount: count,
}) })
for _, g := range c.GatewayList { for _, g := range c.GatewayList {
if g.GatewayStatus != "on" { if g.GatewayStatus != "on" {
continue continue
} }
gateway := Gateway{ gateway := Gateway{
GatewayAlias: g.GatewayAlias, GatewayAlias: g.GatewayAlias,
GatewayStatus: g.GatewayStatus, GatewayStatus: g.GatewayStatus,
IPLimitType: g.IPLimitType, IPLimitType: g.IPLimitType,
IPWhiteList: g.IPWhiteList, IPWhiteList: g.IPWhiteList,
IPBlackList: g.IPBlackList, IPBlackList: g.IPBlackList,
} }
gatewayMap[g.GatewayAlias] = gateway
for _, s := range g.StrategyList.Strategy { for _, s := range g.StrategyList.Strategy {
strategy := Strategy{ strategy := Strategy{
StrategyID: s.StrategyID, StrategyID: s.StrategyID,
Auth: s.Auth, Auth: s.Auth,
ApiKey: s.ApiKey, ApiKey: s.ApiKey,
BasicUserName: s.BasicUserName, BasicUserName: s.BasicUserName,
BasicUserPassword: s.BasicUserPassword, BasicUserPassword: s.BasicUserPassword,
IPLimitType: s.IPLimitType, IPLimitType: s.IPLimitType,
IPWhiteList: s.IPWhiteList, IPWhiteList: s.IPWhiteList,
IPBlackList: s.IPBlackList, IPBlackList: s.IPBlackList,
RateLimitList:s.RateLimitList, RateLimitList: s.RateLimitList,
} }
strategyMap[g.GatewayAlias+":"+s.StrategyID] = strategy
for _, api := range g.ApiList.Apis { for _, api := range g.ApiList.Apis {
path := "/" + g.GatewayAlias + "/" + s.StrategyID + api.RequestURL path := "/" + g.GatewayAlias + "/" + s.StrategyID + api.RequestURL
backendPath := "" backendPath := ""
flag := false flag := false
// 获取后端请求路径 // 获取后端请求路径
for _,b := range g.BackendList.Backend { for _, b := range g.BackendList.Backend {
if b.BackendID == api.BackendID{ if b.BackendID == api.BackendID {
backendPath = b.BackendPath backendPath = b.BackendPath
flag =true flag = true
break break
} }
} }
if !flag && api.BackendID != -1{ if !flag && api.BackendID != -1 {
continue continue
} }
apiInfo := Api{ apiInfo := Api{
RequestURL: api.RequestURL, RequestURL: api.RequestURL,
BackendPath: backendPath, BackendPath: backendPath,
ProxyURL: api.ProxyURL, ProxyURL: api.ProxyURL,
IsRaw:api.IsRaw, IsRaw: api.IsRaw,
ProxyMethod:api.ProxyMethod, ProxyMethod: api.ProxyMethod,
ProxyParams:api.ProxyParams, ProxyParams: api.ProxyParams,
ConstantParams:api.ConstantParams, ConstantParams: api.ConstantParams,
Follow:api.Follow, Follow: api.Follow,
} }
context := Context{ context := Context{
GatewayInfo:gateway, GatewayInfo: gateway,
StrategyInfo:strategy, StrategyInfo: strategy,
ApiInfo:apiInfo, ApiInfo: apiInfo,
Rate:make(map[string]Rate), Rate: make(map[string]Rate),
VisitCount:count, VisitCount: count,
} }
for _, method := range api.RequestMethod {
for _,method := range api.RequestMethod { r.Handle(strings.ToUpper(method), path, r.handle, context)
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)
}
}
} }
} }
package conf package conf
import ( import (
"strings" "goku-ce/utils"
"io/ioutil" "io/ioutil"
"gopkg.in/yaml.v2"
"sort" "sort"
"strings"
"time" "time"
"gopkg.in/yaml.v2"
) )
type Api struct { type Api struct {
ApiList []*ApiInfo `json:"apis" yaml:"apis"` ApiList []*ApiInfo `json:"apis" yaml:"apis"`
} }
type ApiInfo struct { type ApiInfo struct {
ApiID int `json:"apiID" yaml:"api_id"` ApiID int `json:"apiID" yaml:"api_id"`
ApiName string `json:"apiName" yaml:"api_name"` ApiName string `json:"apiName" yaml:"api_name"`
GroupID int `json:"groupID" yaml:"group_id"` GroupID int `json:"groupID" yaml:"group_id"`
RequestURL string `json:"requestURL" yaml:"request_url"` RequestURL string `json:"requestURL" yaml:"request_url"`
RequestMethod []string `json:"requestMethod" yaml:"request_method"` RequestMethod []string `json:"requestMethod" yaml:"request_method"`
BackendID int `json:"backendID" yaml:"backend_id"` BackendID int `json:"backendID" yaml:"backend_id"`
ProxyURL string `json:"proxyURL" yaml:"proxy_url"` ProxyURL string `json:"proxyURL" yaml:"proxy_url"`
ProxyMethod string `json:"proxyMethod" yaml:"proxy_method"` ProxyMethod string `json:"proxyMethod" yaml:"proxy_method"`
IsRaw bool `json:"isRaw" yaml:"is_raw"` IsRaw bool `json:"isRaw" yaml:"is_raw"`
ProxyParams []*Param `json:"proxyParams" yaml:"proxy_params"` ProxyParams []*Param `json:"proxyParams" yaml:"proxy_params"`
ConstantParams []*ConstantParam `json:"constantParams" yaml:"constant_params"` ConstantParams []*ConstantParam `json:"constantParams" yaml:"constant_params"`
Follow bool `json:"follow" yaml:"follow"` Follow bool `json:"follow" yaml:"follow"`
UpdateTime string `json:"updateTime" yaml:"update_time"` UpdateTime string `json:"updateTime" yaml:"update_time"`
CreateTime string `json:"createTime" yaml:"createTime"` CreateTime string `json:"createTime" yaml:"createTime"`
} }
type Param struct { type Param struct {
Key string `json:"key" yaml:"key"` Key string `json:"key" yaml:"key"`
KeyPosition string `json:"keyPosition" yaml:"key_position"` KeyPosition string `json:"keyPosition" yaml:"key_position"`
NotEmpty bool `json:"notEmpty" yaml:"not_empty"` NotEmpty bool `json:"notEmpty" yaml:"not_empty"`
ProxyKey string `json:"proxyKey" yaml:"proxy_key"` ProxyKey string `json:"proxyKey" yaml:"proxy_key"`
ProxyKeyPosition string `json:"proxyKeyPosition" yaml:"proxy_key_position"` ProxyKeyPosition string `json:"proxyKeyPosition" yaml:"proxy_key_position"`
} }
type ConstantParam struct { type ConstantParam struct {
Position string `json:"position" yaml:"position"` Position string `json:"position" yaml:"position"`
Key string `json:"key" yaml:"key"` Key string `json:"key" yaml:"key"`
Value string `json:"value" yaml:"value"` Value string `json:"value" yaml:"value"`
} }
type ApiSlice []map[string]interface{} type ApiSlice []map[string]interface{}
func (a ApiSlice) Len() int { // 重写 Len() 方法 func (a ApiSlice) Len() int { // 重写 Len() 方法
return len(a) return len(a)
} }
func (a ApiSlice) Swap(i, j int){ // 重写 Swap() 方法 func (a ApiSlice) Swap(i, j int) { // 重写 Swap() 方法
a[i], a[j] = a[j], a[i] 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)) 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)) t2, t2Err := time.Parse("2006-01-02 15:04:05", a[i]["updateTime"].(string))
if t1Err == nil && t2Err != nil { if t1Err == nil && t2Err != nil {
return true return true
} else if t1Err == nil && t2Err == nil{ } else if t1Err == nil && t2Err == nil {
if t1.Before(t2) { if t1.Before(t2) {
return false return false
} else { } else {
...@@ -66,62 +68,65 @@ func (a ApiSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到 ...@@ -66,62 +68,65 @@ func (a ApiSlice) Less(i, j int) bool { // 重写 Less() 方法, 从大到
} else if t1Err != nil && t2Err == nil { } else if t1Err != nil && t2Err == nil {
return false return false
} else { } else {
s := []string{a[i]["apiName"].(string),a[j]["apiName"].(string)} s := []string{a[i]["apiName"].(string), a[j]["apiName"].(string)}
sort.Strings(s) sort.Strings(s)
if s[0] == a[i]["apiName"].(string) { if s[0] == a[i]["apiName"].(string) {
return false return false
}else { } else {
return true 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) apiInfo := make(map[int]*ApiInfo)
mapApiList := make([]map[string]interface{},0) mapApiList := make([]map[string]interface{}, 0)
apiList := make([]*ApiInfo,0) apiList := make([]*ApiInfo, 0)
var api Api var api Api
content,err := ioutil.ReadFile(path) content, err := ioutil.ReadFile(path)
if err != nil { 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 { if err != nil {
panic(err) panic(err)
} }
if len(api.ApiList) != 0 { if len(api.ApiList) != 0 {
apiList = api.ApiList apiList = api.ApiList
} }
maxID := 0 maxID := 0
for _,a := range api.ApiList { for _, a := range api.ApiList {
if a.ApiID > maxID { if a.ApiID > maxID {
maxID = a.ApiID maxID = a.ApiID
} }
} }
for _,a := range api.ApiList { for _, a := range api.ApiList {
apiID := a.ApiID apiID := a.ApiID
if apiID == 0 { if apiID == 0 {
apiID = maxID + 1 apiID = maxID + 1
} }
value := map[string]interface{}{ value := map[string]interface{}{
"apiID":apiID, "apiID": apiID,
"apiName":a.ApiName, "apiName": a.ApiName,
"groupID":a.GroupID, "groupID": a.GroupID,
"requestURL":a.RequestURL, "requestURL": a.RequestURL,
"requestMethod":strings.Join(a.RequestMethod,","), "requestMethod": strings.Join(a.RequestMethod, ","),
"updateTime":a.UpdateTime, "updateTime": a.UpdateTime,
"follow": a.Follow, "follow": a.Follow,
} }
mapApiList = append(mapApiList,value) mapApiList = append(mapApiList, value)
apiInfo[apiID] = a apiInfo[apiID] = a
maxID += 1 maxID += 1
} }
sort.Sort(sort.Reverse(ApiSlice(mapApiList))) sort.Sort(sort.Reverse(ApiSlice(mapApiList)))
return apiList,apiInfo,mapApiList,maxID return apiList, apiInfo, mapApiList, maxID
} }
package dao package dao
import ( import (
"fmt"
"goku-ce/server/conf" "goku-ce/server/conf"
"goku-ce/utils" "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 { if conf.GlobalConf.LoginName == loginName && conf.GlobalConf.LoginPassword == loginPassword {
return true return true
} else { } else {
...@@ -15,10 +20,10 @@ func Login(loginName, loginPassword string) (bool) { ...@@ -15,10 +20,10 @@ func Login(loginName, loginPassword string) (bool) {
} }
// 检查用户是否登录 // 检查用户是否登录
func CheckLogin(userToken, loginName string) (bool) { func CheckLogin(userToken, loginName string) bool {
if utils.Md5(conf.GlobalConf.LoginName + conf.GlobalConf.LoginPassword) == userToken { if utils.Md5(conf.GlobalConf.LoginName+conf.GlobalConf.LoginPassword) == userToken {
return true return true
} else { } else {
return false return false
} }
} }
\ No newline at end of file
package utils package utils
import ( import (
"flag"
"fmt" "fmt"
"goku-ce/conf" "goku-ce/conf"
"flag"
"log" "log"
) )
func init() {
ParseArgs()
}
var ConfFilepath string = "./config/goku.conf" var ConfFilepath string = "./config/goku.conf"
var command string = "start" var command string = "start"
func ParseArgs() { 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.StringVar(&ConfFilepath, "c", "./config/goku.conf", "Please provide a valid configuration file path")
flag.Parse() flag.Parse()
err := conf.ReadConfigure(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") log.Fatalln("[error]: Not a valid configuration file, check if the file exists and the validation inside")
} }
} }
...@@ -28,7 +24,7 @@ func ParseArgs() { ...@@ -28,7 +24,7 @@ func ParseArgs() {
func ReloadConf() { func ReloadConf() {
fmt.Println(ConfFilepath) fmt.Println(ConfFilepath)
err := conf.ReadConfigure(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") log.Fatalln("[error]: Not a valid configuration file, check if the file exists and the validation inside")
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册