优化方法的使用

This commit is contained in:
yun
2026-09-19 01:31:34 +08:00
parent 00eba5cc75
commit 407fc49e0c
20 changed files with 1710 additions and 376 deletions
+334
View File
@@ -0,0 +1,334 @@
package ginx_test
// 可运行示例:gin 接入 responsex 的完整用法。
// 每个示例都用 httptest 真实走一遍路由,输出即真实响应体。
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/http/httptest"
"os"
"testing"
"code.yun.ink/pkg/responsex"
ginx "code.yun.ink/pkg/responsex/gin"
"github.com/gin-gonic/gin"
"github.com/yuninks/errorx"
"github.com/yuninks/langx"
)
// ---------- 业务错误码:项目里通常在 errors 包声明一次 ----------
var (
// 第一种写法:text 直接给默认语言文案
ErrSignInvalid = errorx.NewCode("ex_sign_invalid", 41001, "签名校验失败")
// 第二种写法:文案由 langx 的语言表提供(推荐,便于集中维护多语言)
ErrStockNotEnough = errorx.NewCode("ex_stock_not_enough", 50001, "库存不足")
)
// TestMain 里注册一次语言表,等价于项目启动时执行 langx.RegisterDir / RegisterEmbed
func TestMain(m *testing.M) {
langx.RegisterTrans("zh", map[string]string{
"ex_stock_not_enough": "库存不足",
"ex_sign_invalid": "签名校验失败",
})
langx.RegisterTrans("en", map[string]string{
"ex_stock_not_enough": "out of stock",
"ex_sign_invalid": "invalid signature",
})
// 示例演示用:把默认 logger 换成静默实现,避免响应日志混入示例输出。
// 真实项目应接入自己的日志组件,例如:
// responsex.InitOptions(responsex.SetLogger(loggerx.New(...)))
responsex.InitOptions(responsex.SetLogger(silentLogger{}))
gin.SetMode(gin.TestMode)
os.Exit(m.Run())
}
// silentLogger 实现 responsex.Logger,什么都不做
type silentLogger struct{}
func (silentLogger) Info(ctx context.Context, args ...interface{}) {}
func (silentLogger) Infof(ctx context.Context, format string, args ...interface{}) {}
func (silentLogger) Error(ctx context.Context, args ...interface{}) {}
func (silentLogger) Errorf(ctx context.Context, format string, args ...interface{}) {
}
// ---------- 辅助 ----------
func newExampleEngine() *gin.Engine {
r := gin.New()
r.Use(ginx.Middleware())
return r
}
// do 发一次请求,返回响应记录器
func do(r *gin.Engine, method, path string, headers map[string]string) *httptest.ResponseRecorder {
req := httptest.NewRequest(method, path, nil)
for k, v := range headers {
req.Header.Set(k, v)
}
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
return w
}
// body 返回按 key 排序后的紧凑 JSON,便于示例输出稳定
func body(w *httptest.ResponseRecorder) string {
var m map[string]any
if err := json.Unmarshal(w.Body.Bytes(), &m); err != nil {
return w.Body.String()
}
return compact(m)
}
func compact(v any) string {
bs, err := json.Marshal(v)
if err != nil {
return ""
}
return string(bs)
}
// ---------- 1. 最小可用:挂中间件 + 成功响应 ----------
func Example() {
r := newExampleEngine()
r.GET("/ping", func(c *gin.Context) {
ginx.Success(c, gin.H{"pong": true})
})
w := do(r, http.MethodGet, "/ping", nil)
fmt.Println("HTTP", w.Code)
fmt.Println(w.Body.String())
// Output:
// HTTP 200
// {"code":200,"message":"请求成功","data":{"pong":true}}
}
// ---------- 2. Middleware:trace_id 桥接 ----------
func ExampleMiddleware() {
r := newExampleEngine()
r.GET("/order", func(c *gin.Context) {
// 业务侧照旧用 c.Set,不需要关心核心包怎么取值
c.Set("trace_id", "trace-9f8e7d")
ginx.Success(c, gin.H{"order_sn": "SN20240101"})
})
w := do(r, http.MethodGet, "/order", nil)
fmt.Println("c.Set :", w.Body.String())
// 没有 c.Set 时,回落到请求头 X-Request-Id
r2 := newExampleEngine()
r2.GET("/order", func(c *gin.Context) {
ginx.Success(c, "ok")
})
w = do(r2, http.MethodGet, "/order", map[string]string{"X-Request-Id": "req-123"})
fmt.Println("header :", w.Body.String())
// 两者都没有 → 不出现 trace_id 字段
w = do(r2, http.MethodGet, "/order", nil)
fmt.Println("none :", w.Body.String())
// Output:
// c.Set : {"code":200,"message":"请求成功","data":{"order_sn":"SN20240101"},"trace_id":"trace-9f8e7d"}
// header : {"code":200,"message":"请求成功","data":"ok","trace_id":"req-123"}
// none : {"code":200,"message":"请求成功","data":"ok"}
}
// ---------- 3. 参数绑定失败:直接回错误 ----------
func ExampleError() {
r := newExampleEngine()
r.GET("/user", func(c *gin.Context) {
ginx.Error(c, errors.New("EOF: 请求体为空"),
responsex.SetHttpStatusCode(http.StatusBadRequest),
)
})
w := do(r, http.MethodGet, "/user", nil)
fmt.Println("HTTP", w.Code)
fmt.Println(w.Body.String())
// Output:
// HTTP 400
// {"code":400,"message":"EOF: 请求体为空","data":""}
}
// ---------- 4. 业务错误码:code 与多语言文案自动带出 ----------
func ExampleError_businessCode() {
r := newExampleEngine()
r.POST("/order", func(c *gin.Context) {
// errorx 的 New(ctx) 会带上当前请求语言,Error 自动取 Code() 与译文
ginx.Error(c, ErrStockNotEnough.New(c.Request.Context()),
responsex.SetHttpStatusCode(http.StatusConflict))
})
w := do(r, http.MethodPost, "/order", nil)
fmt.Println("zh:", w.Body.String())
w = do(r, http.MethodPost, "/order", map[string]string{"Accept-Language": "en"})
fmt.Println("en:", w.Body.String())
// Output:
// zh: {"code":50001,"message":"库存不足","data":""}
// en: {"code":50001,"message":"out of stock","data":""}
}
// ---------- 5. 校验错误带上字段信息 ----------
func ExampleErrorWithData() {
r := newExampleEngine()
r.POST("/register", func(c *gin.Context) {
ginx.ErrorWithData(c, errors.New("参数校验失败"),
gin.H{
"fields": []string{"email", "phone"},
"detail": "邮箱格式不正确",
},
responsex.SetHttpStatusCode(http.StatusUnprocessableEntity),
)
})
w := do(r, http.MethodPost, "/register", nil)
fmt.Println("HTTP", w.Code)
fmt.Println(body(w))
// Output:
// HTTP 422
// {"code":400,"data":{"detail":"邮箱格式不正确","fields":["email","phone"]},"message":"参数校验失败"}
}
// ---------- 6. 列表分页 ----------
func ExampleSuccessWithPage() {
r := newExampleEngine()
r.GET("/users", func(c *gin.Context) {
// Query: ?page=2&size=10
var page, size int64 = 2, 10
total := int64(35)
// 1) 换算 SQL 的 offset/limit
offset, limit := responsex.GetOffset(int(page), int(size))
_, _ = offset, limit
// 2) 查库(此处给假数据)
rows := []gin.H{{"id": 11, "name": "Alice"}, {"id": 12, "name": "Bob"}}
// 3) 输出
ginx.SuccessWithPage(c, rows, responsex.GetPage(page, size, total))
})
w := do(r, http.MethodGet, "/users?page=2&size=10", nil)
fmt.Println(w.Body.String())
// Output:
// {"code":200,"message":"请求成功","data":[{"id":11,"name":"Alice"},{"id":12,"name":"Bob"}],"pagination":{"page":2,"size":10,"total_page":4,"total_count":35}}
}
// ---------- 7. 多语言文案 + 占位符 ----------
func ExampleFormatMessage() {
langx.AppendTrans("zh", map[string]string{
"ex_order_created": "订单 #sn# 创建成功,金额 #amount# 元",
})
langx.AppendTrans("en", map[string]string{
"ex_order_created": "Order #sn# created, amount #amount#",
})
r := newExampleEngine()
r.POST("/order", func(c *gin.Context) {
ginx.MsgMapData(c, "ex_order_created",
map[string]string{"sn": "SN20240101", "amount": "99.00"},
gin.H{"order_sn": "SN20240101"},
)
})
w := do(r, http.MethodPost, "/order", nil)
fmt.Println("zh:", w.Body.String())
w = do(r, http.MethodPost, "/order", map[string]string{"Accept-Language": "en"})
fmt.Println("en:", w.Body.String())
// Output:
// zh: {"code":200,"message":"订单 SN20240101 创建成功,金额 99.00 元","data":{"order_sn":"SN20240101"}}
// en: {"code":200,"message":"Order SN20240101 created, amount 99.00","data":{"order_sn":"SN20240101"}}
}
// ---------- 8. 单占位符快捷方法 ----------
func ExampleMsgKV() {
langx.AppendTrans("zh", map[string]string{
"ex_welcome": "欢迎回来,#name#",
})
r := newExampleEngine()
r.POST("/login", func(c *gin.Context) {
ginx.MsgKV(c, "ex_welcome", "name", "Yun")
})
w := do(r, http.MethodPost, "/login", nil)
fmt.Println(w.Body.String())
// Output:
// {"code":200,"message":"欢迎回来,Yun"}
}
// ---------- 9. 自定义响应:非标准 code / 自定义响应头 ----------
func ExampleCustom() {
r := newExampleEngine()
r.POST("/pay", func(c *gin.Context) {
ginx.Custom(c,
responsex.SetCode(20001),
responsex.SetMessage("支付受理中"),
responsex.SetData(gin.H{"pay_no": "PAY20240101"}),
responsex.SetHttpStatusCode(http.StatusAccepted),
responsex.SetHeader("X-Pay-No", "PAY20240101"),
)
})
w := do(r, http.MethodPost, "/pay", nil)
fmt.Println("HTTP", w.Code)
fmt.Println("X-Pay-No:", w.Header().Get("X-Pay-No"))
fmt.Println(w.Body.String())
// Output:
// HTTP 202
// X-Pay-No: PAY20240101
// {"code":20001,"message":"支付受理中","data":{"pay_no":"PAY20240101"}}
}
// ---------- 10. 完整骨架:全局初始化 + 中间件 + 业务错误 + 分页 ----------
func Example_completeServer() {
// 1) 启动时全局初始化(一般放 main / wire)
responsex.InitOptions(
responsex.SetDefaultSuccessCode(0),
responsex.SetDefaultErrorCode(-1),
)
defer responsex.InitOptions( // 示例里恢复,避免影响其它用例
responsex.SetDefaultSuccessCode(200),
responsex.SetDefaultErrorCode(400),
)
// 2) 路由
r := gin.New()
r.Use(ginx.Middleware()) // 关键:桥接 trace_id 与语言
r.GET("/goods", func(c *gin.Context) {
if c.Query("sign") == "" {
ginx.Error(c, ErrSignInvalid.New(c.Request.Context()))
return
}
ginx.Success(c, gin.H{"goods": []string{"apple", "pear"}})
})
w := do(r, http.MethodGet, "/goods", map[string]string{"X-Request-Id": "t-1"})
fmt.Println("fail:", w.Body.String())
w = do(r, http.MethodGet, "/goods?sign=abc", map[string]string{"X-Request-Id": "t-2"})
fmt.Println("ok: ", w.Body.String())
// Output:
// fail: {"code":41001,"message":"签名校验失败","data":"","trace_id":"t-1"}
// ok: {"code":0,"message":"请求成功","data":{"goods":["apple","pear"]},"trace_id":"t-2"}
}
-38
View File
@@ -1,38 +0,0 @@
package ginx
import (
"code.yun.ink/pkg/responsex"
"github.com/gin-gonic/gin"
)
func Error(ctx *gin.Context, err error, ops ...responsex.Option) {
responsex.Error(ctx, ctx.Writer, err, ops...)
}
func ErrorWithData(ctx *gin.Context, err error, data any, ops ...responsex.Option) {
responsex.ErrorWithData(ctx, ctx.Writer, err, data, ops...)
}
func ErrorStr(ctx *gin.Context, msg string, ops ...responsex.Option) {
responsex.ErrorStr(ctx, ctx.Writer, msg, ops...)
}
func Success(ctx *gin.Context, data any, ops ...responsex.Option) {
responsex.Success(ctx, ctx.Writer, data, ops...)
}
func SuccessWithPage(ctx *gin.Context, data any, page responsex.Pagination, ops ...responsex.Option) {
responsex.SuccessWithPage(ctx, ctx.Writer, data, &page, ops...)
}
func Custom(ctx *gin.Context, ops ...responsex.Option) {
responsex.ResponseCtx(ctx, ctx.Writer, ops...)
}
func MsgMapData(ctx *gin.Context, msgKey string, format map[string]string, data any, ops ...responsex.Option) {
responsex.FormatMessage(ctx, ctx.Writer, msgKey, format, data, ops...)
}
func MsgKV(ctx *gin.Context, msgKey string, k string, v string, ops ...responsex.Option) {
responsex.FormatMessage(ctx, ctx.Writer, msgKey, map[string]string{k: v}, nil, ops...)
}
Regular → Executable
+81 -3
View File
@@ -1,14 +1,16 @@
package ginx_test
import (
"context"
"encoding/json"
"errors"
"net/http/httptest"
"testing"
"code.yun.ink/pkg/responsex"
respgin "code.yun.ink/pkg/responsex/ginx"
respgin "code.yun.ink/pkg/responsex/gin"
"github.com/gin-gonic/gin"
"github.com/yuninks/langx"
)
func init() {
@@ -35,6 +37,8 @@ func newGinCtx(w *httptest.ResponseRecorder) *gin.Context {
func TestSuccess(t *testing.T) {
w := httptest.NewRecorder()
c := newGinCtx(w)
// c.Set("trace_id","adada")
c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), "trace_id", "adada"))
respgin.Success(c, "hello world")
@@ -169,8 +173,8 @@ func TestErrorStr(t *testing.T) {
respgin.ErrorStr(c, "string error")
body := decodeBody(t, w)
if body["message"] == "" {
t.Error("message should not be empty")
if body["message"] != "string error" {
t.Errorf("message = %v, want 'string error'", body["message"])
}
}
@@ -275,3 +279,77 @@ func TestCustom(t *testing.T) {
t.Errorf("code = %v, want 100", body["code"])
}
}
// ---------- Middleware:trace_id 桥接 ----------
func newEngine() *gin.Engine {
r := gin.New()
r.Use(respgin.Middleware())
return r
}
func TestMiddlewareBridgesTraceID(t *testing.T) {
r := newEngine()
r.GET("/t", func(c *gin.Context) {
c.Set("trace_id", "trace-from-gin")
respgin.Success(c, "ok")
})
w := httptest.NewRecorder()
r.ServeHTTP(w, httptest.NewRequest("GET", "/t", nil))
body := decodeBody(t, w)
if body["trace_id"] != "trace-from-gin" {
t.Errorf("trace_id = %v, want trace-from-gin (需要 Middleware 桥接)", body["trace_id"])
}
}
func TestMiddlewareTraceIDFromHeader(t *testing.T) {
r := newEngine()
r.GET("/t", func(c *gin.Context) {
respgin.Success(c, "ok")
})
req := httptest.NewRequest("GET", "/t", nil)
req.Header.Set("X-Request-Id", "req-header-id")
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
body := decodeBody(t, w)
if body["trace_id"] != "req-header-id" {
t.Errorf("trace_id = %v, want req-header-id", body["trace_id"])
}
}
// ---------- Middleware:按 Accept-Language 翻译 ----------
func TestMiddlewareBridgesLanguage(t *testing.T) {
langx.AppendTrans("en", map[string]string{
"responsex_success": "success",
"not_found": "resource not found",
})
r := newEngine()
r.GET("/t", func(c *gin.Context) {
respgin.Success(c, "ok")
})
r.GET("/e", func(c *gin.Context) {
respgin.ErrorStr(c, "not_found")
})
req := httptest.NewRequest("GET", "/t", nil)
req.Header.Set("Accept-Language", "en")
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
if body := decodeBody(t, w); body["message"] != "success" {
t.Errorf("message = %v, want success", body["message"])
}
req = httptest.NewRequest("GET", "/e", nil)
req.Header.Set("Accept-Language", "en")
w = httptest.NewRecorder()
r.ServeHTTP(w, req)
if body := decodeBody(t, w); body["message"] != "resource not found" {
t.Errorf("message = %v, want 'resource not found'", body["message"])
}
}
Executable
+128
View File
@@ -0,0 +1,128 @@
package ginx
// Package ginx 是 responsex 的 gin 适配层。
//
// 依赖隔离:本包只依赖 gin、responsex 核心与 langx,
// import 本包不会引入 go-zero / gorm。
//
// go-zero 的 trace 提取(OpenTelemetry span 里的 trace_id)需要另外按需 import:
//
// import _ "code.yun.ink/pkg/responsex/gozerotrace"
//
// import 路径:code.yun.ink/pkg/responsex/gin
import (
"context"
"code.yun.ink/pkg/responsex"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/yuninks/langx"
)
// traceIDCtxKey 是 gin 侧约定的 trace_id key(c.Set / c.Get 使用)
const traceIDCtxKey = "trace_id"
// Middleware 桥接 gin 与 responsex 核心:
//
// 1. 把 gin 的 trace_id 写进标准 context(核心包据此输出 trace_id);
// 2. 按 Accept-Language 写入语言(核心包据此翻译文案)。
//
// 为什么需要它:gin 的 c.Value() 读不到 c.Set() 存的值,而 responsex 核心只认标准
// context,没有中间件时 trace_id 不会出现在响应里。
//
// r := gin.New()
// r.Use(ginx.Middleware())
//
// 业务侧只需像以前一样调用 c.Set("trace_id", id),响应会自动带上。
func Middleware(ops ...responsex.Option) gin.HandlerFunc {
return func(c *gin.Context) {
if c.Request == nil {
c.Next()
return
}
responsex.InitOptions(ops...)
c.Request = c.Request.WithContext(bridgeCtx(c))
c.Next()
}
}
// bridgeCtx 由 gin.Context 构造标准 context(trace_id + 语言)
func bridgeCtx(c *gin.Context) context.Context {
ctx := context.Background()
if c.Request != nil {
ctx = c.Request.Context()
}
responsex.SetTraceKey(traceIDCtxKey)
// trace_id:优先 gin context,其次请求头
if v, ok := c.Get(traceIDCtxKey); ok {
if s, ok := v.(string); ok && s != "" {
uuid := uuid.New().String()
ctx = context.WithValue(ctx, traceIDCtxKey, uuid)
}
} else if val, ok := c.Get("trace_id"); ok {
ctx = context.WithValue(ctx, traceIDCtxKey, val)
} else if s := c.GetHeader("X-Request-Id"); s != "" {
ctx = context.WithValue(ctx, traceIDCtxKey, s)
} else {
ctx = context.WithValue(ctx, traceIDCtxKey, uuid.New().String())
}
// Accept-Language:核心包按此语言取译文
if lang := c.GetHeader("Accept-Language"); lang != "" {
ctx = langx.SetCtxLang(ctx, lang)
}
return ctx
}
// requestCtx 返回用于构造响应的 context。
// 在中间件建立的 ctx 基础上,于写响应前再同步一次 trace_id,
// 这样 handler 内部才调用 c.Set("trace_id", ...) 也能生效。
func requestCtx(c *gin.Context) context.Context {
if c.Request == nil {
return context.Background()
}
ctx := c.Request.Context()
if v, ok := c.Get(traceIDCtxKey); ok {
if s, ok := v.(string); ok && s != "" {
ctx = context.WithValue(ctx, traceIDCtxKey, s)
}
}
return ctx
}
func Error(c *gin.Context, err error, ops ...responsex.Option) {
responsex.Error(requestCtx(c), c.Writer, err, ops...)
}
func ErrorWithData(c *gin.Context, err error, data any, ops ...responsex.Option) {
responsex.ErrorWithData(requestCtx(c), c.Writer, err, data, ops...)
}
func ErrorStr(c *gin.Context, msg string, ops ...responsex.Option) {
responsex.ErrorStr(requestCtx(c), c.Writer, msg, ops...)
}
func Success(c *gin.Context, data any, ops ...responsex.Option) {
responsex.Success(requestCtx(c), c.Writer, data, ops...)
}
func SuccessWithPage(c *gin.Context, data any, page responsex.Pagination, ops ...responsex.Option) {
responsex.SuccessWithPage(requestCtx(c), c.Writer, data, &page, ops...)
}
func Custom(c *gin.Context, ops ...responsex.Option) {
responsex.ResponseCtx(requestCtx(c), c.Writer, ops...)
}
func MsgMapData(c *gin.Context, msgKey string, format map[string]string, data any, ops ...responsex.Option) {
responsex.FormatMessage(requestCtx(c), c.Writer, msgKey, format, data, ops...)
}
func MsgKV(c *gin.Context, msgKey string, k string, v string, ops ...responsex.Option) {
responsex.FormatMessage(requestCtx(c), c.Writer, msgKey, map[string]string{k: v}, nil, ops...)
}
Executable
+61
View File
@@ -0,0 +1,61 @@
module code.yun.ink/pkg/responsex/gin
go 1.22.4
require (
code.yun.ink/pkg/responsex v1.0.1
github.com/gin-gonic/gin v1.9.1
github.com/yuninks/langx v0.0.7
)
require (
github.com/bytedance/sonic v1.9.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/openzipkin/zipkin-go v0.4.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/yuninks/errorx v1.0.0 // indirect
github.com/zeromicro/go-zero v1.6.4 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.19.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/sdk v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/automaxprocs v1.5.3 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.20.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/grpc v1.63.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Executable
+157
View File
@@ -0,0 +1,157 @@
code.yun.ink/pkg/responsex v1.0.1 h1:S0n0CSkJIKPyIOxyfWCSsiUond3FyvLKxCzvM35wABw=
code.yun.ink/pkg/responsex v1.0.1/go.mod h1:c36aY9efSBS9kmI6/toES3R82xVMW740e6g/H0GE4io=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuninks/errorx v1.0.0 h1:/AS4dSEVPkfvs3hJFYgqYBFLKyVvxFV32XXbMXoHwvk=
github.com/yuninks/errorx v1.0.0/go.mod h1:N9e4ShfCTkLjHnGShAG0x9n2SYtCDKhKDMxRmyr05hU=
github.com/yuninks/langx v0.0.7 h1:QUt27h/FjnT7//759GoM/+p4ew+HBr10ZN/fkqeQfyA=
github.com/yuninks/langx v0.0.7/go.mod h1:nAylzjNIjCThhEQSJsIKP8Vhja0aJlcyig+NsNPZLSk=
github.com/zeromicro/go-zero v1.6.4 h1:GvZXxxwl1Lby/gIHxHwN/ZNmXl1WFJa1DvoVgqgttUs=
github.com/zeromicro/go-zero v1.6.4/go.mod h1:dQ39Zoz20/6x/SUhFXyEEg8lWjl+CO3dzg8Je2xG63Q=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y=
go.opentelemetry.io/otel/exporters/zipkin v1.19.0 h1:EGY0h5mGliP9o/nIkVuLI0vRiQqmsYOcbwCuotksO1o=
go.opentelemetry.io/otel/exporters/zipkin v1.19.0/go.mod h1:JQgTGJP11yi3o4GHzIWYodhPisxANdqxF1eHwDSnJrI=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=