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

168 lines
4.5 KiB
Go

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.

//go:build server || (!server && !client)
package main
import (
"log"
"os"
"os/signal"
"syscall"
internalinterceptor "github.com/noahlann/nnet/internal/interceptor"
"github.com/noahlann/nnet/internal/interceptor/builtin"
"github.com/noahlann/nnet/pkg/interceptor"
"github.com/noahlann/nnet/pkg/nnet"
routerpkg "github.com/noahlann/nnet/pkg/router"
)
// This example demonstrates interceptor chain usage.
// Interceptors can validate, transform, or filter data before it reaches handlers.
func main() {
cfg := &nnet.Config{
Addr: "tcp://:8084",
Codec: &nnet.CodecConfig{
DefaultCodec: "json",
EnableProtocolEncode: false,
},
}
srv, err := nnet.NewServer(cfg)
if err != nil {
log.Fatal("create server:", err)
}
// 创建拦截器链
// 拦截器1最小长度验证至少5字节
minLenInterceptor := builtin.MinLengthInterceptor(5)
// 拦截器2最大长度验证最多100字节
maxLenInterceptor := builtin.MaxLengthInterceptor(100)
// 拦截器3自定义验证拦截器验证数据不为空且不为"forbidden"
customInterceptor := interceptor.HandlerFunc(func(data []byte, ctx nnet.Context, next interceptor.Chain) ([]byte, bool, error) {
if len(data) == 0 {
return nil, false, interceptor.New("data cannot be empty")
}
if string(data) == "forbidden" {
return nil, false, interceptor.New("forbidden data")
}
// 记录到上下文
ctx.Set("intercepted", true)
ctx.Set("data_length", len(data))
return next.Next(data, ctx)
})
// 使用自定义匹配器匹配所有请求并在handler中应用拦截器
// 路由1验证端点使用拦截器链
srv.Router().RegisterCustom(
func(input routerpkg.MatchInput, ctx nnet.Context) bool {
data := input.Raw
// 匹配以"validate"开头的数据
return len(data) >= 8 && string(data[:8]) == "validate"
},
func(ctx nnet.Context) error {
rawData := ctx.Request().Raw()
// 提取实际数据(跳过"validate"命令)
var actualData []byte
if len(rawData) > 8 {
actualData = rawData[8:]
// 跳过空格或换行
for len(actualData) > 0 && (actualData[0] == ' ' || actualData[0] == '\n') {
actualData = actualData[1:]
}
}
// 如果没有数据,使用默认测试数据
if len(actualData) == 0 {
actualData = []byte("test data for validation")
}
// 执行拦截器链
interceptors := []interceptor.Interceptor{
minLenInterceptor,
maxLenInterceptor,
customInterceptor,
}
data, continueProcessing, err := internalinterceptor.Execute(actualData, ctx, interceptors...)
if err != nil {
return ctx.Response().Write(map[string]any{
"error": err.Error(),
"valid": false,
"message": "validation failed",
})
}
if !continueProcessing {
return ctx.Response().Write(map[string]any{
"error": "processing stopped",
"valid": false,
})
}
// 获取拦截器设置的值
intercepted := ctx.GetBool("intercepted")
dataLength := ctx.GetInt("data_length")
return ctx.Response().Write(map[string]any{
"valid": true,
"data": string(data),
"intercepted": intercepted,
"data_length": dataLength,
"message": "validation passed",
})
},
)
// 路由2简单的echo
srv.Router().RegisterString("echo", func(ctx nnet.Context) error {
data := ctx.Request().Raw()
return ctx.Response().Write(map[string]any{
"echo": string(data),
})
})
// 路由3测试端点使用最小长度拦截器
srv.Router().RegisterString("test", func(ctx nnet.Context) error {
rawData := ctx.Request().Raw()
// 只使用最小长度拦截器
data, continueProcessing, err := internalinterceptor.Execute(rawData, ctx, minLenInterceptor)
if err != nil {
return ctx.Response().Write(map[string]any{
"error": err.Error(),
"valid": false,
})
}
if !continueProcessing {
return ctx.Response().Write(map[string]any{
"error": "processing stopped",
"valid": false,
})
}
return ctx.Response().Write(map[string]any{
"valid": true,
"data": string(data),
})
})
log.Println("interceptor_server listening on :8084")
log.Println("Interceptors:")
log.Println(" - MinLengthInterceptor (min: 5 bytes)")
log.Println(" - MaxLengthInterceptor (max: 100 bytes)")
log.Println(" - CustomInterceptor (rejects 'forbidden')")
if err := srv.Start(); err != nil {
log.Fatal("start server:", err)
}
defer srv.Stop()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
}