-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net/goai: I want to customize the response 500 content #3747
Comments
GF 目前处理响应只有一个结果 See: Line 239 in 6e5ce98
无法自定义状态码,在一些 需要根据这些状态码响应
目前 GF 没有支持这个,有一个想法参考: 在 server:
address: ":8199"
openapiPath: "/api.json"
swaggerPath: "/swagger" package main
import (
"context"
"net/http"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/net/goai"
)
type HelloCreateReq struct {
g.Meta `path:"/hello" method:"POST"`
Name string `v:"required" dc:"Your name"`
Age int `v:"required|between:1,200" dc:"Your age"`
}
type HelloCreateRes struct {
g.Meta `successStatusCode:"201" errorStatusCode:"400,500"`
ID uint64 `json:"id,string" dc:"ID"`
}
type HelloGetReq struct {
g.Meta `path:"/hello/{id}" method:"GET"`
// ID ID
ID uint64 `json:"id,string" dc:"ID" in:"path" v:"required"`
}
type HelloGetRes struct {
g.Meta `errorStatusCode:"400,500"`
ID uint64 `json:"id,string" dc:"ID"`
Name string `json:"name" dc:"Name"`
Age int `json:"age" dc:"Age"`
}
type Hello struct{}
func (c *Hello) Create(ctx context.Context, r *HelloCreateReq) (*HelloCreateRes, error) {
return &HelloCreateRes{ID: 1}, nil
}
func (c *Hello) Get(ctx context.Context, r *HelloGetReq) (*HelloGetRes, error) {
return &HelloGetRes{
ID: r.ID,
Name: "john",
Age: 18,
}, nil
}
func main() {
s := g.Server()
s.Use(ghttp.MiddlewareHandlerResponse)
s.Group("/", func(group *ghttp.RouterGroup) {
group.Bind(
new(Hello),
)
})
// 设置响应数据结构
oai := s.GetOpenApi()
oai.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
oai.Config.CommonResponseDataField = "Data"
// 错误的响应
dataResp := &goai.Schemas{}
dataResp.Set("code", goai.SchemaRef{
Value: &goai.Schema{
Type: "integer",
Format: "int32",
Title: "业务状态码",
Description: "业务状态码",
},
})
dataResp.Set("message", goai.SchemaRef{
Value: &goai.Schema{
Type: "string",
Title: "业务状态描述",
Description: "业务状态描述",
},
})
dataResp.Set("data", goai.SchemaRef{
Value: &goai.Schema{
Type: "object",
Title: "业务数据",
Description: "业务数据",
Nullable: true,
},
})
oai.Components.Schemas.Set("bizmodel.HTTPResponse", goai.SchemaRef{
Value: &goai.Schema{
Type: "object",
Properties: dataResp,
},
})
// 错误的响应状态码匹配
oai.Components.Responses = goai.Responses{
// 也许我们需要将 key 的空格去掉???
http.StatusText(http.StatusBadRequest): goai.ResponseRef{
Value: &goai.Response{
Description: "BadRequest",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
http.StatusText(http.StatusNotFound): goai.ResponseRef{
Value: &goai.Response{
Description: "NotFound",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
http.StatusText(http.StatusInternalServerError): goai.ResponseRef{
Value: &goai.Response{
Description: "InternalServerError",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
}
s.Run()
}
|
GF currently processes responses with only one result See: Line 239 in 6e5ce98
The status code cannot be customized and represents different meanings in some Need to respond according to these status codes
Currently GF does not support this, here is an idea: Currently GF does not support this. One idea is to set the server:
address: ":8199"
openapiPath: "/api.json"
swaggerPath: "/swagger" package main
import (
"context"
"net/http"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/net/goai"
)
type HelloCreateReq struct {
g.Meta `path:"/hello" method:"POST"`
Name string `v:"required" dc:"Your name"`
Age int `v:"required|between:1,200" dc:"Your age"`
}
type HelloCreateRes struct {
g.Meta `successStatusCode:"201" errorStatusCode:"400,500"`
ID uint64 `json:"id,string" dc:"ID"`
}
type HelloGetReq struct {
g.Meta `path:"/hello/{id}" method:"GET"`
// ID ID
ID uint64 `json:"id,string" dc:"ID" in:"path" v:"required"`
}
type HelloGetRes struct {
g.Meta `errorStatusCode:"400,500"`
ID uint64 `json:"id,string" dc:"ID"`
Name string `json:"name" dc:"Name"`
Age int `json:"age" dc:"Age"`
}
type Hello struct{}
func (c *Hello) Create(ctx context.Context, r *HelloCreateReq) (*HelloCreateRes, error) {
return &HelloCreateRes{ID: 1}, nil
}
func (c *Hello) Get(ctx context.Context, r *HelloGetReq) (*HelloGetRes, error) {
return &HelloGetRes{
ID: r.ID,
Name: "john",
Age: 18,
}, nil
}
func main() {
s := g.Server()
s.Use(ghttp.MiddlewareHandlerResponse)
s.Group("/", func(group *ghttp.RouterGroup) {
group.Bind(
new(Hello),
)
})
//Set the response data structure
oai := s.GetOpenApi()
oai.Config.CommonResponse = ghttp.DefaultHandlerResponse{}
oai.Config.CommonResponseDataField = "Data"
//wrong response
dataResp := &goai.Schemas{}
dataResp.Set("code", goai.SchemaRef{
Value: &goai.Schema{
Type: "integer",
Format: "int32",
Title: "Business Status Code",
Description: "Business status code",
},
})
dataResp.Set("message", goai.SchemaRef{
Value: &goai.Schema{
Type: "string",
Title: "Business Status Description",
Description: "Business status description",
},
})
dataResp.Set("data", goai.SchemaRef{
Value: &goai.Schema{
Type: "object",
Title: "Business Data",
Description: "Business data",
Nullable: true,
},
})
oai.Components.Schemas.Set("bizmodel.HTTPResponse", goai.SchemaRef{
Value: &goai.Schema{
Type: "object",
Properties: dataResp,
},
})
// Wrong response status code match
oai.Components.Responses = goai.Responses{
// Maybe we need to remove the spaces from key? ? ?
http.StatusText(http.StatusBadRequest): goai.ResponseRef{
Value: &goai.Response{
Description: "BadRequest",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
http.StatusText(http.StatusNotFound): goai.ResponseRef{
Value: &goai.Response{
Description: "NotFound",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
http.StatusText(http.StatusInternalServerError): goai.ResponseRef{
Value: &goai.Response{
Description: "InternalServerError",
Content: map[string]goai.MediaType{
"application/json": {Schema: &goai.SchemaRef{Ref: "bizmodel.HTTPResponse"}},
},
},
},
}
s.Run()
}
|
@shuqingzai 厉害,你这个也能实现自定义状态码 |
可以引用啊,需要手动加到 你说的无法引用,是因为 GF 没法手动设置某个接口的多个状态码响应,只有一个 实际上 |
@shuqingzai 我再换一个描述
但我想实现的是
|
懂了~~,这确实是一个 BUG ,schema 的引用前缀被写死了,应该需要判断,如果是根节点开头,不需要拼接前缀 但是问题的核心是 GF 没有对某个接口进行多个 response 的配置,所以还是我一开始说的,需要在 因为即使你可以配置进去,也没法使用多个响应,一样没法用 我自己改了一点,可以适配,可以参考下
|
Got it~~, this is indeed a BUG. The reference prefix of the schema is hard-coded. It should be judged. If it starts with the root node, there is no need to splice the prefix. But the core of the problem is that GF does not configure multiple responses for a certain interface, so as I said at the beginning, you need to define Because even if you can configure it, you can't use multiple responses, it still won't work. I changed it a bit myself and it can be adapted. You can refer to it below.
|
这里的核心只有schema 的引用前缀被写死,404,500 本来就是通用状态码 通过重写自定义 /api.json 即可完成高度自定义就行了 |
The core here is that only the reference prefix of the schema is hard-coded. 404 and 500 are originally universal status codes. By rewriting the custom /api.json, a high degree of customization can be achieved. |
@ivothgle |
|
千言万语不如代码一贴 func enhanceOpenAPIDoc(s *ghttp.Server) {
s.BindHandler("/api.json", openapiSpec)
s.BindHandler("/swagger-ui/", func(r *ghttp.Request) {
r.Response.Write(MySwaggerUITemplate)
r.ExitAll()
})
openapi := s.GetOpenApi()
openapi.Config.CommonResponse = model.DefaultHandlerResponse{}
openapi.Config.CommonResponseDataField = `Data`
openapi.Config.IgnorePkgPath = true
openapi.Security = &goai.SecurityRequirements{{"bearerAuth": []string{}}}
openapi.Components.SecuritySchemes = goai.SecuritySchemes{
"bearerAuth": goai.SecuritySchemeRef{
Value: &goai.SecurityScheme{
Type: "http",
Scheme: "bearer",
BearerFormat: "JWT",
},
},
}
}
func genOpenapi(s *ghttp.Server) {
var (
ctx = context.TODO()
err error
methods []string
)
for _, item := range s.GetRoutes() {
switch item.Type {
case ghttp.HandlerTypeMiddleware, ghttp.HandlerTypeHook:
continue
}
if item.Handler.Info.IsStrictRoute {
methods = []string{item.Method}
if gstr.Equal(item.Method, "ALL") {
methods = ghttp.SupportedMethods()
}
for _, method := range methods {
err = s.GetOpenApi().Add(goai.AddInput{
Path: item.Route,
Method: method,
Object: item.Handler.Info.Value.Interface(),
})
if err != nil {
s.Logger().Fatalf(ctx, `%+v`, err)
}
}
}
}
}
func openapiSpec(req *ghttp.Request) {
genOpenapi(req.Server)
// 过滤免登录的接口
si, _ := g.Cfg("secure").Get(req.GetCtx(), "secure.ignore")
unauthenticated := make(map[string]struct{})
for _, url := range si.Strings() {
unauthenticated[url] = struct{}{}
}
for url, path := range req.Server.GetOpenApi().Paths {
tag := "xxxx"
if path.Get != nil {
path.Get.Tags[0] = path.Get.Tags[0] + " - " + tag
if _, ok := unauthenticated[url]; ok {
path.Get.Security = &goai.SecurityRequirements{}
}
}
if path.Post != nil {
path.Post.Tags[0] = path.Post.Tags[0] + " - " + tag
if _, ok := unauthenticated[url]; ok {
path.Post.Security = &goai.SecurityRequirements{}
}
}
if path.Put != nil {
path.Put.Tags[0] = path.Put.Tags[0] + " - " + tag
if _, ok := unauthenticated[url]; ok {
path.Put.Security = &goai.SecurityRequirements{}
}
}
if path.Delete != nil {
path.Delete.Tags[0] = path.Delete.Tags[0] + " - " + tag
if _, ok := unauthenticated[url]; ok {
path.Delete.Security = &goai.SecurityRequirements{}
}
}
}
req.Response.Write(req.Server.GetOpenApi())
} 我都已经在操作 goai.Operation 了,就没必要往 gf 里面增加负担了,把前缀放开就可以了 |
你贴的代码都是 GF 已经实现的逻辑,我不明白为啥你还要重写一次
|
你说的都对! |
Everything you said is right! |
@ivothgle @shuqingzai 大家好,关于 |
@ivothgle @shuqingzai Hello everyone, regarding the support of |
@gqcn 获取到了 GeOpentAPI 对象,却因为代码写死了无法扩展,唉 |
@gqcn obtained the GeOpentAPI object, but it cannot be expanded because the code is written to death, alas. |
你好,是否有个别属性没有公开,请具体描述一下呢? |
Hello, are there any individual attributes that have not been made public? Please describe them in detail? |
@gqcn 强哥好,我个人觉得目前goai模块的主要问题可能还是对于非200状态码的处理不是很理想。诚然在全200状态下文档的支持度已经很好了,但对于非200派的而言实际上还是需要其他状态码管理的,我们非200派维护一些东西会比较拧巴哈哈哈哈。目前添加状态码或者是状态码的具体example都需要进行很长一串结构体的构造,例如下面这个比较丑陋的实现: func AddResponseStatus(openapi *goai.OpenApiV3, path string, method string, contentType string, object interface{}, status string, description string) {
// Add schema
openapi.Add(goai.AddInput{
Object: object,
})
location := strings.ReplaceAll(reflect.TypeOf(object).PkgPath(), "/", ".")
name := reflect.TypeOf(object).Name()
target := findMethod(openapi.Paths[path], method)
// Prevent duplicate
if _, exist := target.Responses[status]; exist {
return
}
target.Responses[status] = goai.ResponseRef{
Value: &goai.Response{
Content: goai.Content{
contentType: goai.MediaType{
Schema: &goai.SchemaRef{
Ref: location + "." + name,
},
},
},
Description: description,
},
}
} 然后再添加examples的schema,最后的api.json会类似这样: "/api/v1/auth/login": {
"post": {
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/project.api.auth.v1.LoginReq"
}
}
}
},
"responses": {
"200": { some default data },
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/project.api.CommonRes"
},
"examples": {
"Code 401: login failed": {
"value": {
"code": 401,
"message": "incorrect Username or Password",
"data": null
}
}
}
}
},
"description": ""
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/project.api.CommonRes"
},
"examples": {
"Code 1: User not exist": {
"value": {
"code": 1,
"message": "User not exist",
"data": null
}
},
"Code 2: Wrong password": {
"value": {
"code": 2,
"message": "Wrong password",
"data": null
}
},
"Code 3: Not allowed": {
"value": {
"code": 3,
"message": "Not allowed",
"data": null
}
}
}
}
},
"description": ""
}
},
"summary": "User Login",
"tags": [
"Auth"
]
}
}, 为了添加非200的状态码往往都需要进行类似这样的操作,并且由于他们和规范路由并不存在强关联,很多时候很容易在文档中漏掉某些状态码,进而导致文档实际上并不完全可用。同时虽然已经封装了添加的函数,但每次添加状态都会调用一次,导致最后实际上还是会在api包里写一大坨东西进去。这块要说是项目本身的问题确实也有一些,但既然GoFrame已经有了相对比较完善的goai文档管理机制,我觉得实际上可以暴露一些类似的方法给到开发者,或者是直接在规范路由的 如果暴露方法的话我个人认为对于非200派而言最重要的应该有两个,一个是上面提到的添加状态码schema,另一个是添加examples(对应特定状态码下的error code)。这样的话goai本身不需要太多改动,只需要让开发者自行决定schema是什么样,然后再注入到文档里就可以了。 另一种方案可能是在现有的tag基础上添加一个 var LoginRes403 = map[int]gcode.Code{
1: gcode.New(1, "User not exist", nil),
2: gcode.New(2, "Wrong password", nil),
3: gcode.New(3, "Not allowed", nil),
} 然后通过解析这个变量来生成对应的examples,这样不仅方便,也更容易管理对应api的错误状态。不过这个方法和commen response的耦合比较大,可能对于框架来说不是一个好的解决方案。 GoFrame的规范路由真的是一个很棒的解决方案,我个人会比较重视这块,因为前端调用和后端排障很多时候都需要一份可靠的文档,而在规范路由的情况下大部分时间开发者也都不需要花费过多的精力在api文档的维护上。强哥可以费心看看这块还有没有优化的空间,我go的经验比较少所以上面提到的一些方案可能都比较僵硬。 |
@UncleChair 框架原本在设计自动API接口文档生成的时候,就没有考虑不同返回状态码的接口文档生成,因为我们的初衷是代码文档一致性维护、自动化生成、只满足大部分的场景。 不同返回状态码数据结构定义如果需要实现不同状态码的代码文档一致性维护,我粗略想了一下,其实可以参考 type XxxRes struct {
g.Meta `path:"/xxx"` // 这里是接口返回的主要描述,针对2xx的状态码
goai.Status403 *Status403Struct // 这个是状态码403时的数据结构描述
goai.Status500 *Status500Struct // 这个是状态码500时的数据结构描述
// 以此类推
} 其中 有更好的建议欢迎一起讨论。 复杂example的维护那么文档的example怎么来实现呢?example通常是大块代码,那么可以结合资源管理的能力来实现!资源管理是将静态资源打包到二进制文件中一起发布的能力( https://goframe.org/pages/viewpage.action?pageId=1114671 ),并且在 type XxxReq struct {
g.Meta `path:"/xxx" example:"resource/example/xxx/200.json"` // 通过example标签指定资源管理器中的具体example代码文件
goai.Status403 Status403Struct `example:"resource/example/xxx/403.json"`
goai.Status500 Status500Struct `example:"resource/example/xxx/500.json"`
// 以此类推
} 并且这个能力在开发时是自动读取的本地文件,在编译发布时是从资源管理器读取的(编译发布即可无需做额外操作),和资源管理器设计的能力一致。 同时,这些能力需要在 |
@UncleChair When the framework originally designed the automatic API interface document generation, it did not consider the generation of interface documents with different return status codes, because our original intention was to maintain the consistency of code documents and automatically generate them, which only satisfies most scenarios. Different return status code data structure definitionsIf you need to maintain the consistency of code documents for different status codes, I gave it a rough thought. In fact, you can refer to the type XxxReq struct {
g.Meta `path:"/xxx"` // Here is the main description of the interface, for the 2xx status code
goai.Status403 Status403Struct // This is the data structure description when status code 403
goai.Status500 Status500Struct // This is the data structure description when the status code is 500
// and so on
} And this capability is automatically read from local files during development, and is read from the resource manager during compilation and release (no additional operations are required for compilation and release), which is consistent with the capability designed by the resource manager. Maintenance of complex examplesSo how to implement the example of the document? Example is usually a large block of code, so it can be achieved by combining resource management capabilities! Resource management is the ability to package static resources into binary files and publish them together (https://goframe.org/pages/viewpage.action?pageId=1114671), and under the type XxxReq struct {
g.Meta `path:"/xxx" example:"resource/example/xxx/200.json"` // Specify the specific example code file in the resource manager through the example tag
goai.Status403 Status403Struct `example:"resource/example/xxx/403.json"`
goai.Status500 Status500Struct `example:"resource/example/xxx/500.json"`
// and so on
} At the same time, these capabilities need to be enhanced in |
@gqcn 感谢强哥的思路,结合源码的一些内容我这边也想了一个关于不同返回状态码数据结构定义的方案:
举个例子就是: type XXXReq struct {
g.Meta `status:"201" example:"xxx.json"`
Status string `json:"status" des:"server status" eg:"OK!"`
Status404Error *Error404 `status:"404" example:"xxx.json"`
} 这样有一个好处就是goai不需要维护一些保留字段来保证可以解析到对应的结构体,也不会和用户现有的字段产生冲突(因为只将包含status的字段解析为某个状态下的schema),设置状态码也比较方便。同时status字段也可以用于默认返回状态码的设置,解析req就可以拿到(这块尝试写了个简单的实现),也能保证满足用户所有2xx的需求 不知道这样从框架的角度是否是一个好的实现 |
@gqcn Thanks to Brother Qiang for his ideas. Combining some contents of the source code, I also thought of a solution for defining different return status code data structures:
An example is: type XXXReq struct {
g.Meta `status:"201" example:"xxx.json"`
Status string `json:"status" des:"server status" eg:"OK!"`
Status404Error *Error404 `status:"404" example:"xxx.json"`
} One advantage of this is that goai does not need to maintain some reserved fields to ensure that the corresponding structure can be parsed, and it will not conflict with the user's existing fields (because only fields containing status are parsed into schema in a certain state) , it is also more convenient to set the status code. At the same time, the status field can also be used to set the default return status code, which can be obtained by parsing req (I tried to write a simple [implementation](https://github.com/gogf/gf/compare/master.. .UncleChair:gf:goai/http_status_enhance)), which can also ensure that all 2xx needs of users are met I don’t know if this is a good implementation from a framework perspective. |
使用 |
It is a good idea to use |
定义太多不同的返回数据结构可能确实会造成一些使用上的混乱,其实最好还是在有common response的情况下自动复用,我也是更倾向于直接复用。不过考虑到可能用户的response handler会有定制的错误结构体需求,可能实现一个类似override的流程会更好一些? 目前的构想是当包含 |
Defining too many different return data structures may indeed cause some confusion in use. In fact, it is best to automatically reuse when there is a common response. I also prefer direct reuse. However, considering that the user's response handler may have customized error structure requirements, it may be better to implement a process similar to override? The current idea is that when a field containing the |
@UncleChair 我主要担忧的是,定义这些状态码返回数据结构对业务数据结构的侵入性,开发者在编写和使用业务数据结构的时候还需要关心这些非业务相关的数据结构,体验会很不好。但如果是在 我不确定有没有这种脱离 |
@UncleChair My main concern is that defining these status code return data structures is intrusive to business data structures. Developers also need to care about these non-business-related data structures when writing and using business data structures, and the experience will be very bad. . But if you define the data structures of these different status codes in I'm not sure if there is such a business scenario that breaks away from the |
@gqcn 在req里定义状态码返回数据结构确实是会对业务理解造成一定的影响,不过我感觉应该也不完全是坏事。目前来说的话我会把req作为返回数据的一个 对于开发者编写和使用业务数据结构这块我能想到的缺点可能就是字段会在scan的时候和某些dao的字段重复,不过我相信这应该是命名规范或者说是设计问题,心智负担确实是有一些,但在项目的一些设计下其实是完全可控的,就比如规定使用statusxxxRes这种字段来命名之类的。更重要的是其实通过这样的方式,返回状态也被api纳入了管理之下,不管是通过tag解析json example还是其它一些方法,在这种情况下一个请求的所有状态和它所在的api是可以有强关联的,这其实无形中减少了开发者的管理负担。 在 不过话又说回来req的结构比较干净的话看起来确实比较舒服,用起来表面上的心智负担也会更低,不过确实需要一个更有效地可以将错误状态和api关联起来的方案。或者干脆给req加个返回状态和example的方法怎么样?例如这样: type XXXReq {}
func (r *XXXReq ) Status() map[string]interface{}{
return (状态码和数据结构)
} 解析的时候就可以直接添加了,错误管理也可以用相同的方法拿到数据,同时也保证了业务数据结构的清晰。 |
@gqcn Defining the status code return data structure in req will indeed have a certain impact on business understanding, but I feel it is not entirely a bad thing. For now, I will use req as an The disadvantage I can think of for developers writing and using business data structures may be that the fields will be repeated with the fields of some DAOs during scanning. However, I believe this should be a naming convention or a design issue. The mental burden is indeed There are some, but they are actually completely controllable under some designs of the project, such as stipulating the use of fields such as statusxxxRes for naming. More importantly, in this way, the return status is also managed by the API. Whether it is parsing json example through tags or some other methods, in this case all the status of a request and the API where it is located can be If there is a strong correlation, this actually reduces the management burden on developers. Defining error structures in But then again, if the structure of req is relatively clean, it does look more comfortable, and the mental load on the surface will be lower when using it. However, a more effective solution is needed to associate error status with the API. Or how about simply adding a method to req that returns status and example? For example: type XXXReq {}
func (r *XXXReq ) Status() map[string]interface{}{
return (status code and data structure)
} It can be added directly during parsing, and error management can also use the same method to obtain data, while also ensuring a clear business data structure. |
@UncleChair 通过接口实现的方式来定义不同状态码的返回数据结构是个很棒的想法👍🏻!这样既能解决不同状态码扩展的问题,也能避免对业务数据结构的侵入。这里有几个点需要明确一下:
type StatusCode = int
type ResponseStatusDefinition interface{
func ResponseStatusMap() map[StatusCode]any
}
@shuqingzai @ivothgle @hailaz @wln32 @oldme-git 大家一起看看有没更好的建议没有呢? |
Go version
go1.22
GoFrame version
2.7.0
Can this bug be reproduced with the latest release?
Option Yes
What did you do?
I want to customize the response 500 content,
output
"500": {
"$ref": "#/components/schemas/InternalServerError"
}
He should be "#/components/responses/InternalServerError", see https://swagger.io/docs/specification/describing-responses/
What did you see happen?
It is not possible to customize the reference response structure in OpenAI because its prefix is always fixed
code is:
gf/net/goai/goai.go
Line 227 in 6e5ce98
What did you expect to see?
He should be "#/components/responses/InternalServerError", see https://swagger.io/docs/specification/describing-responses/
The text was updated successfully, but these errors were encountered: