strategy.go 3.3 KB
Newer Older
Y
Your Name 已提交
1 2 3 4 5 6
package gateway

import (
	"fmt"
	"net/http"

Y
Your Name 已提交
7 8
	"github.com/pkg/errors"

Y
Your Name 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	log "github.com/eolinker/goku-api-gateway/goku-log"
	"github.com/eolinker/goku-api-gateway/goku-node/common"
	plugin_executor "github.com/eolinker/goku-api-gateway/node/gateway/plugin-executor"
	"github.com/eolinker/goku-api-gateway/node/router"
	access_field "github.com/eolinker/goku-api-gateway/server/access-field"
)

//Strategy strategy
type Strategy struct {
	ID     string
	Name   string
	Enable bool

	apiRouter router.APIRouter

	accessPlugin       []plugin_executor.Executor
	globalAccessPlugin []plugin_executor.Executor

	authPlugin map[string]plugin_executor.Executor

	isNeedAuth bool
}

//Router router
func (r *Strategy) Router(w http.ResponseWriter, req *http.Request, ctx *common.Context) {
	if !r.Enable {

		go log.Info("[ERROR]StrategyID is out of service!")

		ctx.SetStatus(500, "500")

		ctx.SetBody([]byte("[ERROR]StrategyID is out of service!"))
		return
	}

	ctx.SetStrategyName(r.Name)
	ctx.SetStrategyId(r.ID)
	ctx.LogFields[access_field.Strategy] = fmt.Sprintf("\"%s %s\"", r.ID, r.Name)

	if r.isNeedAuth {
		// 需要校验
Y
Your Name 已提交
50 51
		ok, err := r.auth(ctx)
		if err != nil {
Y
Your Name 已提交
52 53
			// 校验失败
			ctx.SetStatus(403, "403")
Y
Your Name 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
			//ctx.SetBody([]byte("[ERROR]Illegal authorization type!"))
			ctx.SetBody([]byte(err.Error()))
			return
		}
		if !ok {
			return
		}
	}
	for _, strategyAccess := range r.accessPlugin {
		if strategyAccess.IsAuth() {
			continue
		}
		fmt.Println(strategyAccess.IsAuth())
		isContinued, err := strategyAccess.Execute(ctx)
		if isContinued {
			continue
		}
		if err != nil {
			ctx.SetStatus(403, "403")
			ctx.SetBody([]byte(err.Error()))
Y
Your Name 已提交
74 75 76 77 78 79
			return
		}
	}
	r.apiRouter.ServeHTTP(w, req, ctx)
}

Y
Your Name 已提交
80
func (r *Strategy) auth(ctx *common.Context) (bool, error) {
Y
Your Name 已提交
81 82 83 84
	requestID := ctx.RequestId()
	authType := ctx.Request().GetHeader("Authorization-Type")
	authPlugin, has := r.authPlugin[authType]
	if !has {
Y
Your Name 已提交
85 86 87
		errInfo := errors.New(" Illegal authorization type:" + authType)
		log.Warn(requestID, errInfo.Error())
		return false, errInfo
Y
Your Name 已提交
88 89 90 91 92
	}

	isContinue, err := authPlugin.Execute(ctx)
	if isContinue == false {
		pluginName := authNames[authType]
Y
Your Name 已提交
93 94

		var errInfo error
Y
Your Name 已提交
95 96
		// 校验失败
		if err != nil {
Y
Your Name 已提交
97 98 99
			errInfo = errors.New(" access auth:[" + pluginName + "] error:" + err.Error())
			log.Warn(requestID, errInfo.Error())
			return false, errInfo
Y
Your Name 已提交
100 101 102
		}
		log.Info(requestID, " auth [", pluginName, "] refuse")

Y
Your Name 已提交
103
		return false, nil
Y
Your Name 已提交
104 105
	}
	log.Debug(requestID, " auth [", authType, "] pass")
Y
Your Name 已提交
106
	return true, nil
Y
Your Name 已提交
107
}
Y
Your Name 已提交
108
func (r *Strategy) accessFlow(ctx *common.Context) bool {
Y
Your Name 已提交
109 110 111 112 113 114
	for _, handler := range r.accessPlugin {

		flag, _ := handler.Execute(ctx)

		if flag == false && handler.IsStop() {

Y
Your Name 已提交
115
			return false
Y
Your Name 已提交
116 117
		}
	}
Y
Your Name 已提交
118
	return true
Y
Your Name 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132
}

func (r *Strategy) accessGlobalFlow(ctx *common.Context) {
	// 全局插件不中断
	for _, handler := range r.globalAccessPlugin {
		_, _ = handler.Execute(ctx)

	}
}

//HandlerAPINotFound 当接口不存在时调用
func (r *Strategy) HandlerAPINotFound(ctx *common.Context) {
	// 未匹配到api
	// 执行策略access 插件
Y
Your Name 已提交
133 134 135 136
	if !r.accessFlow(ctx) {
		r.accessGlobalFlow(ctx)
		return
	}
Y
Your Name 已提交
137 138 139
	// 执行全局access 插件
	r.accessGlobalFlow(ctx)

Y
Your Name 已提交
140 141 142 143 144 145 146
	if ctx.StatusCode() == 0 {
		// 插件可能会设置状态码
		log.Info(ctx.RequestId(), " URL dose not exist!")
		ctx.SetStatus(404, "404")
		ctx.SetBody([]byte("[ERROR]URL dose not exist!"))
	}

Y
Your Name 已提交
147
}