Skip to content

Commit

Permalink
refactor: 正确处理 MarshalFunc 返回错误可能是 Problem
Browse files Browse the repository at this point in the history
  • Loading branch information
caixw committed Jan 5, 2024
1 parent a158328 commit 9f08443
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 20 deletions.
10 changes: 4 additions & 6 deletions filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ type FilterFunc = func() (string, LocaleStringer)
// v 必须是指针类型,否则无法对其内容进行修改;
type FilterFuncOf[T any] func(name string, v *T) FilterFunc

// RuleFuncOf 数据验证规则
//
// 这是验证器与错误信息的组合。
// RuleFuncOf 验证器与错误信息的组合
//
// 传递参数为字段名与需要验证的值;
// 返回字段名和错误信息,如果验证成功,则返回两个空值;
Expand Down Expand Up @@ -219,9 +217,9 @@ func (ctx *Context) newFilterContext(exitAtError bool) *FilterContext {
//
// name 为 f 中验证对象的整体名称;
// f 为验证方法,其原型为 func(fp *FilterContext)
// 往 fp 写入的信息,其字段名均会以 name 作为前缀写入到当前对象 v 中。
// fp 的各种属性均继承自 v。
func (v *FilterContext) New(name string, f func(f *FilterContext)) *FilterContext {
// 往 c 参数写入的信息,其字段名均会以 name 作为前缀写入到当前对象 v 中。
// c 的各种属性均继承自 v。
func (v *FilterContext) New(name string, f func(c *FilterContext)) *FilterContext {
f(newFilterContext(v.exitAtError, v.name+name, v.Context(), v.problem))
return v
}
Expand Down
31 changes: 21 additions & 10 deletions mimetype/jsonp/jsonp.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,57 @@ const Mimetype = "application/javascript"

type contextKeyType int

type options struct {
key string
unsetProblem string
}

const contextKey contextKeyType = 1

var once = &sync.Once{}

// Install 安装 JSONP 的处理方式
//
// callbackKey 用于指定回函数名称的查询参数名称
func Install(callbackKey string, s web.Server) {
if callbackKey == "" {
panic("callbackKey 不能为空")
// key 用于指定回函数名称的查询参数名称;
// unsetProblem 表示查询参数中没有 key 指定的参数或是参数值为空时的应该返回的 [web.Problem]
func Install(s web.Server, key, unsetProblem string) {
if key == "" {
panic("key 不能为空")
}

if unsetProblem == "" {
panic("unsetProblem 不能为空")
}

once.Do(func() {
s.Vars().Store(contextKey, callbackKey)
s.Vars().Store(contextKey, options{key: key, unsetProblem: unsetProblem})
})
}

func Marshal(ctx *web.Context, v any) ([]byte, error) {
if ctx == nil {
return json.Marshal(v)
panic("ctx 不能为空")
}

data, err := json.Marshal(v)
if err != nil {
return nil, err
return nil, ctx.Error(err, web.ProblemNotAcceptable)
}

key, found := ctx.Server().Vars().Load(contextKey)
v, found := ctx.Server().Vars().Load(contextKey)
if !found {
return data, nil
}
o := v.(options)

q, err := ctx.Queries(true)
if err != nil {
return data, err
}

callback := q.String(key.(string), "")
callback := q.String(o.key, "")
if callback == "" {
return nil, web.NewLocaleError("unset callback name")
return nil, ctx.Problem(o.unsetProblem)
}

b := errwrap.StringBuilder{}
Expand Down
6 changes: 3 additions & 3 deletions mimetype/jsonp/jsonp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestJSONP(t *testing.T) {
HTTPServer: &http.Server{Addr: ":8080"},
})
a.NotError(err).NotNil(s)
Install("callback", s)
Install(s, "callback", web.ProblemBadRequest)

s.NewRouter("def", nil).Get("/jsonp", func(ctx *web.Context) web.Responser {
return web.OK("jsonp")
Expand All @@ -32,13 +32,13 @@ func TestJSONP(t *testing.T) {
defer s.Close(0)

servertest.Get(a, "http://localhost:8080/jsonp").Header("accept", Mimetype).Do(nil).
Status(http.StatusNotAcceptable). // 由 [web.Context.Render] 决定此值
Status(http.StatusBadRequest).
BodyEmpty()

servertest.Get(a, "http://localhost:8080/jsonp?callback=cb").Header("accept", Mimetype).Do(nil).
StringBody(`cb("jsonp")`)

servertest.Get(a, "http://localhost:8080/jsonp?cb=cb").Header("accept", Mimetype).Do(nil).
Status(http.StatusNotAcceptable).
Status(http.StatusBadRequest).
BodyEmpty()
}
6 changes: 5 additions & 1 deletion output.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@ func (ctx *Context) Render(status int, body any) {
data, err := ctx.Marshal(body)
if err != nil {
// [Problem.Apply] 并未调用 [Context.Render],应该不会死循环。
ctx.Error(err, ProblemNotAcceptable).Apply(ctx)
if p, ok := err.(*Problem); ok {
p.Apply(ctx)
} else {
ctx.Error(err, ProblemNotAcceptable).Apply(ctx)
}
return
}

Expand Down

0 comments on commit 9f08443

Please sign in to comment.