Skip to content
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: supports configuring multiple response status documents #3750

Open
shuqingzai opened this issue Aug 30, 2024 · 2 comments
Open

net/goai: supports configuring multiple response status documents #3750

shuqingzai opened this issue Aug 30, 2024 · 2 comments

Comments

@shuqingzai
Copy link

GF 目前处理响应只有一个结果 200

See:

if _, ok := operation.Responses[responseOkKey]; !ok {

无法自定义状态码,在一些 2xx 状态中代表不同含义,参考: 201 Created

需要根据这些状态码响应

  1. 创建成功,希望可以设置为 201
  2. 异步任务,延迟处理的,希望为 202

目前 GF 没有支持这个,有一个想法参考:

xxxRes.Meta 中设置 successStatusCodeerrorStatusCode 标签,框架可以解析且设置对应的 HTTP Status Code 文档

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()
}
  1. HelloCreateRes 中设置 successStatusCode201,那么应该生成 201 文档,也设置了 400500 且这两个 response 的文档可以在文档的 components.responses 中通过 HTTP Status text 匹配到,也应该设置到文档中
  2. HelloGetRes 中没有设置 successStatusCode 则应该默认生成 200 的文档

Originally posted by @shuqingzai in #3747 (comment)

@Issues-translate-bot Issues-translate-bot changed the title net/goai: 支持配置多个响应状态文档 net/goai: supports configuring multiple response status documents Aug 30, 2024
@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


GF currently processes responses with only one result 200

See:

if _, ok := operation.Responses[responseOkKey]; !ok {

The status code cannot be customized and represents different meanings in some 2xx states. Reference: 201 Created

Need to respond according to these status codes

  1. Created successfully, hope it can be set to 201
  2. Asynchronous tasks, delayed processing, hope to be 202

Currently GF does not support this, here is an idea:

Set the successStatusCode or errorStatusCode tag in xxxRes.Meta, the framework can parse and set the corresponding HTTP Status Code document

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()
}
  1. Set successStatusCode to 201 in HelloCreateRes, then the 201 document should be generated, 400 and 500 are also set, and the two response documents can be found in the components.responses' of the document is matched by HTTP Status text and should also be set to the document
  2. If successStatusCode is not set in HelloGetRes, a document of 200 should be generated by default

Originally posted by @shuqingzai in #3747 (comment)

@shuqingzai
Copy link
Author

See: #3747

shuqingzai added a commit to shuqingzai/gf that referenced this issue Sep 1, 2024
1. set `successStatusCode` tag into xxxRes.Meta
2. set `errorStatusCode` tag into xxxRes.Meta

link: gogf#3750 gogf#3747
shuqingzai added a commit to shuqingzai/gf that referenced this issue Sep 1, 2024
1. set `successStatusCode` tag into xxxRes.Meta
2. set `errorStatusCode` tag into xxxRes.Meta

link: gogf#3750 gogf#3747
shuqingzai pushed a commit to shuqingzai/gf that referenced this issue Sep 2, 2024
1. reference to common error responses
2. If a RefLink starts with a components root node, no default prefix is added.

link: gogf#3750 gogf#3747
shuqingzai pushed a commit to shuqingzai/gf that referenced this issue Sep 2, 2024
1. reference to common error responses
2. If a RefLink starts with a components root node, no default prefix is added.

link: gogf#3750 gogf#3747
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants