You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package filter
import (
"net/http"
"net/rpc"
"github.com/mafanr/juz/api/req"
"github.com/mafanr/juz/api/stats"
"github.com/mafanr/g"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
)
/*
请求拦截过滤插件.
该模块组的核心目的是给网关提供扩展性插件.
我们应该尽量保证网关核心层的不变性所有的变化的插件都在fileter中实现.
*/
// 可以在以下四个地方添加拦截插件
//1.请求开始前
//2.接受到服务的返回数据,返回给客户端之前
//3.请求失败后
// 拦截器顺序
//1.拦截器分为网关自带和用户定义的
//2.每个拦截器应该具有优先级编号
//3.按照优先级来调用拦截器
type Filter struct {
Rpc *rpc.Client
}
type Result struct {
Status int
Ecode int
Emsg string
}
// 收到请求路由前的hook
func (f *Filter) BeforeRoute(r *req.Request) Result {
// 黑白名单
err := f.checkBW(r)
if err != nil {
g.Info("BeforeRoute failed", zap.Error(err))
// 统计被阻挡数
stats.Limits.With(prometheus.Labels{
"api_id": r.Api.APIID,
"service": r.Api.Service,
"app": r.Api.App,
}).Inc()
return Result{http.StatusForbidden, g.ForbiddenC, g.ForbiddenE}
}
// 参数校验
err = f.verifyParam(r)
if err != nil {
g.Info("BeforeRoute failed", zap.Error(err))
return Result{http.StatusBadRequest, g.ParamInvalidC, g.ParamInvalidE}
}
// 流量路由
f.trafficRoute(r)
// 检查当
return Result{}
}
// 调用目标服务前的hook
func (f *Filter) BeforeCall(r *req.Request) Result {
code, err := f.IncApiRate(r)
if err != nil {
// 统计被阻挡数
stats.Limits.With(prometheus.Labels{
"api_id": r.Api.APIID,
"service": r.Api.Service,
"app": r.Api.App,
}).Inc()
return Result{code, g.AccessLimitedC, err.Error()}
}
return Result{}
}
// 调用目标服务完成后的hook
func (f *Filter) AfterCall(r *req.Request) Result {
// 并发数减1
f.DecApiRate(r)
return Result{}
}
func (f *Filter) RouteFailed(r *req.Request) Result {
return Result{}
}