从v2.0版本开始,框架的Server组件额外提供了规范化的路由注册方式,更加适合团队规范化的使用场景、业务复杂度更高的项目。规范路由实现了以下特性:
v2.0
Server
API
OpenAPIv3
SwaggerUI
注意一下哦:规范路由与原有的函数、对象、分组路由方式都是框架的HTTP Server组件并存支持的路由注册方式,是为了解决一些规范化和自动化管理接口的场景,更适用于团队多人协作使用。其他的路由方式,特别是框架v1版本的函数、对象注册方式也是在新版本支持的哈!看个人使用习惯进行合理选择哟。
HTTP Server
v1
请教一下,现在可以做到在swagger接口页面全局设置header头的鉴权字段么
我试了是支持的。 goai里面的结构体对应的就是openApi3官网的yaml结构.
openapi.Components = goai.Components{ SecuritySchemes: goai.SecuritySchemes{ "ApiKeyAuth": goai.SecuritySchemeRef{ Ref: "", // 暂时还不知道该值是干什么用的 Value: &goai.SecurityScheme{ Type: "apiKey", In: "header", Name: "token", }, }, },}
感谢
beautiful mtgnorton
openapi.Components = goai.Components{ SecuritySchemes: goai.SecuritySchemes{ "ApiKeyAuth": goai.SecuritySchemeRef{ Ref: "", // 暂时还不知道该值是干什么用的 Value: &goai.SecurityScheme{ Type: "apiKey", In: "header", Name: "token", }, }, }, }
代码加上了,swagger页面上出现了Authorize按钮,设置key之后,使用try it out 发出的请求并没有在header带上token。 怎么回事呢?
经过研究发现,openapi.Components配置SecuritySchema之后只是让swagger定义了一个校验的方式,并没有让每一个API使用这个校验,必须在每一个path上配置上这个校验,才能真正生效。但是发现gf并没有支持这个功能,经过修改gf的代码,实现了该效果:swagger_ui.png (1217×599) (smartbear.co) 类似于这个图上的 那个 Authorize按钮和每个API后边的那个锁图标,实际体验可以看 Swagger UI 这个demo的apiKey方式。
openapi.Components
SecuritySchema
swagger
path
gf
Authorize
demo
apiKey
我实现的方式为:
SecuritySchemes
修改我本地的E:\go-workspace\pkg\mod\github.com\gogf\gf\v2@v2.0.0-rc3\protocol\goai\goai_path.go文件中的91行,把option的初始化改为:
E:\go-workspace\pkg\mod\github.com\gogf\gf\v2@v2.0.0-rc3\protocol\goai\goai_path.go
option
var ( path = Path{} inputMetaMap = gmeta.Data(inputObject.Interface()) outputMetaMap = gmeta.Data(outputObject.Interface()) isInputStructEmpty = oai.doesStructHasNoFields(inputObject.Interface()) inputStructTypeName = oai.golangTypeToSchemaName(inputObject.Type()) outputStructTypeName = oai.golangTypeToSchemaName(outputObject.Type()) operation = Operation{ Responses: map[string]ResponseRef{}, Security: &SecurityRequirements{SecurityRequirement{"APIKeyAuth": []string{}}}, // 这一行是新增 } )
此时再看swaggerUI页面就可以看到那个 Authorize按钮和每个API后边的那个锁图标。使用try it out 按钮也可以实现在header上自动加上想要的token。
swaggerUI
try it out
header
token
郭强 海亮 gf是否有更好的方式支持,而不是我这样修改gf的源码?
这个只是OpenAPI接口定义的展示而已,真正要实现功能还是得依靠中间件。
OpenAPI
关于全局设置OpenAPI属性,可以Server.GetOpenAPI后修改goai.OpenAPI对象对应属性即可,不用修改源码。
Server.GetOpenAPI
goai.OpenAPI
focus-single项目示例代码有例子:https://github.com/gogf/focus-single/blob/786c16e7516dd68c11352cc4fce3152353c20c60/internal/cmd/cmd.go#L110
focus-single
首先,全局设置OpenAPI属性的确可以使用Server.GetOpenAPI后修改goai.OpenAPI,但是我这里的需求是每一个api的path对应的swagger定义,不是全局的,所以这里提供的方法是无效的。另外,无论是中间件也好,hook也好,都是request--》response 的流程过程中进行拦截处理,而我这里的诉求是在server启动之后,生成openAPI的定义时候触发。所以,中间件不行。目前只能改gf的源码。请仔细看我的问题描述
删除
总结后分享到这里常见问题(FAQ)
分享规范化路由学习笔记
强哥,自动生成的 swagger 页面中,【Responses】栏只列出了 200 状态。
[假装有截图]
是否有办法能自定义每个路由的 400、401、403、500 错误呢?
或者为所有路由配置统一的 400、401、403、500 错误。
这个只有自己获取Server的OpenApi对象后自己去扩展了,无法在Req对象中通过结构体标签绑定,因为那样太复杂了,可维护性太低。
OpenApi
Req
http://gf.l11.cn/ 规范化路由代码生成
你这有点意思哦。
你这个是真的棒...点赞
https://gitee.com/Guwengo/gf_code_auto
基于后端 结构体 自动生成CURD代码的版本来了
基于GF自己的模板引擎制作
更方便
更便捷
gf 工具里面应该集成这个功能,模板能定义最好,起码把该有的文件给创建了.哈哈
swagger ui在使用gf-user-demo时,没有try it out按钮哦
关于goframe2.0规范路由的个人见解
使用v2.0.1版本及以上版本会发现 swaggerUI被修改了为 redoc了。redoc缺少了 Try it console。能不能提供一个方式,可以选择swaggerUI或者redoc 么?
可以自己开个静态页面展示自己的SwaggerUI,然后仅使用Server的OpenAPI地址。
灵活性太受限了
比如一个接口,可能有多个路由,但入参结构体相同,应如何处理呢?
一接口多路由:参考常见问题。
请求参数复用:将公用的结构体进行嵌套复用。
指这个吗 “ 1、在规范路由下,同一接口如何支持多种HTTP Method提交方式 ”
我的意思是,/api/hello, /welcome/sayhello, 两个路由地址,可能指向同一个 handler (如 Tom.SayHello())
规范路由要求会比较严格一些,"规范"二字由此而来。你描述的case已经不太规范了,但你可以通过两种方式来实现:
case
1、适当规范你的路由设计,使用不同的路由前缀来区分不同的业务模块。这样你定义的输入输出结构体不用重新定义,只需要在路由注册的时候使用分组路由,绑定不同的路由前缀。
2、定义不同的Req结构体,内部嵌套相同的结构体来实现。
如果希望自定义response 该如何处理,比如 code 为 string 类型,
不同的分组路由,使用不一样的response。 历史遗留系统,返回样式五花八门
请教一下,新版本的路由注册,我有点迷,普通的用法我会
比如我发送 GET 和 PUT 请求,是 user/:id ,那么 g.Meta 里面的 path 标签应该如何写呢?
如果我打算把参数放在路径里面,不通过 struct 里面的其它属性来定义,我该如何在控制器中获取到这个 :id 呢?
我用了
g.RequestFromCtx(ctx).Get("id")
好像获取不到
无论参数是request body还是url上的,都需要在结构体里定义。
g.Meta `path:"/user/{uuid}" method:"put" `
确实取到值了,大哥你好聪明啊,我读完文档,没找到相关用法,谢谢!
这个我在文档的确看到了 是需要在 g.Meta的tag里写
接口文档-OpenAPIv3
在 三、常用协议标签的表格里
我又遇到了一个新的疑问
type RoleUpdateReq struct { g.Meta `path:"/backend/role" tags:"三体" method:"put" summary:"故事角色"` Id uint `json:"id" v:"required#请选择需要修改的角色"` RoleBaseReq }
这里不能是 Id 否则获取到的就是个莫名其妙的数值,我传的 Id 是2,但是获取到的是下面的 13
{ Id: 13, Avatar: "222", Name: "string", Nickname: "string", SurvivalStage: "string", Nationality: "string", Achievement: "string", Gender: 0, Content: "string", IfShow: 0, }
如果把 Id 改成 RoleId ,就可以正确获取到值,这是为什么呢?
写成下面就是正常的,这是规定吗?
type RoleUpdateReq struct { g.Meta `path:"/backend/role" tags:"三体" method:"put" summary:"故事角色"` RoleId uint `json:"role_id" v:"required#请选择需要修改的角色"` RoleBaseReq }
问题已解决,补充一下这个答案。
一位朋友提示会不会是中间件赋值的影响
我在断点调试的过程中发现了 ID 被覆盖了
原因是 JWT 中 IdentityKey 我用了 id 这个作为 key
如果替换成一个其它的字段,就不会影响前端业务字段了
func init() { auth = jwt.New(&jwt.GfJWTMiddleware{ Realm: "threeboby", Key: []byte("mingyuejishiyou"), Timeout: time.Minute * 300, MaxRefresh: time.Minute * 5, IdentityKey: "auth_unique_key", TokenLookup: "header: Authorization, query: token, cookie: jwt", TokenHeadName: "Bearer", TimeFunc: time.Now, Authenticator: Authenticator, Unauthorized: Unauthorized, PayloadFunc: PayloadFunc, IdentityHandler: IdentityHandler, }) }
可能我的理解级别不够,分组路由不挺好吗,为什么非要卷出一个规范路由,这所谓的规范,反正让我背这一串字符串,挺难,接口上百个,感觉这字符串难维护,比如:`path:"/user/{uuid}" method:"put" `
不同场景,选择适合的就好。
对于这种规范路由的方式,如果返回的格式不同,是不是就不能用了?比如想下面两种格式。如果能用的话,统一返回值处理那里应该怎么做?
{ "code": 200, "message": "success" "data":{ "id":1 } } { "code": 200, "message": "success" "data":[ {"id":1}, {"id":2}, ] "total":2 }
重写MiddlewareHandlerResponse 根据业务需要去处理返回内容.
另外 建议将业务内容包到data内部保持风格一致.
{ "code": 200, "message": "success", "data": { "total": 2, "list": [ { "id": 1 }, { "id": 2 } ] } }
请教一下,请求结构体中的参数从 http header 获取参数的情况,使用 in:"header" 是否可以直接获取值。
我本地测试发现不行,不知是框架暂时不支持还是我使用姿势不正确,望可以解答。谢谢。
type GetUserInfoReq struct { g.Meta `tags:"用户" sm:"获取用户信息"` Authorization string `json:"Authorization" dc:"用户token" in:"header"` }
还没实现这个标签 先用手动获取赋值处理吧.
感谢。现在是直接由ctx,从header里取的。
token := g.RequestFromCtx(ctx).GetHeader("Authorization")
auth在控制器处理的话复用效率比较低,一般在前置中间件中处理,而中间件取header数据也是从request对象取,其实并不冲突.
两个问题
type RoleUpdateReq struct { g.Meta `path:"/backend/role" tags:"三体" method:"get/post" auth:"true"` }
ctrl & logic 层可以拿到RoleUpdateReq,通过反射就能拿 tags/methmod...
我想是现在中间层,在请求处理前进行统一处理,也就是在controller层前一层处理掉没有登录的请求,并且返回统一的响应值,按照你的说话,可能我需要在进去在处理,那每一个函数都要有自己的鉴权处理,我觉得可能有一些麻烦
我也是想这样,之前看到你问的这个,自己也研究了,没找到办法。后面调试的时候,无意中看到ghttp.Request有个
GetServeHandler方法,可以拿到路由注册的controller函数,而req这个结构体就是函数的第二个参数。因此可以通过反射得到gmeta信息。具体方法如下:
r := g.RequestFromCtx(ctx) //拿到requesthandler := r.GetServeHandler() //拿到handlerif handler != nil && handler.Handler.Info.Type != nil && handler.Handler.Info.Type.NumIn() == 2 { var objectReq = reflect.New(handler.Handler.Info.Type.In(1)) //反射获得函数第二个参数,第二个参数就是req的结构体 g.Dump(gmeta.Data(objectReq))}可能你会觉得这样反射很奇怪,然而,官方就是这么做的。因为在绑定路由的时候,只传了controller进去。这个结构体只能通过controller的函数的第二个参数获取。他的实现在这里https://github.com/gogf/gf/blob/9aa872e7058999eec025883fe5939bccc9235b3c/net/ghttp/ghttp_server_router.go#L98
原谅我吐槽一下,这个api结构体的字段tag都有哪些,从截图里我看到了dc是字段描述,好歹文档提一嘴吧
接着往下看就有了
好嘞,多谢
我想出一个前台接口文档,一个后台接口文档,同一个项目,应该怎么弄
SetListener
有一个问题, 设置参数 in:query 但是还是从请求体里获取的 那设置这个的必要性在哪呢,这个并不是从query取得值
规范路由下预检OPTIONS请求怎么通过;
规范路由只定义了post方法;
发起预检请求直接返回404 not found了,没有进到cors中间件
请问密文请求,解密后如何按现在的规范传入这种结构呢
func (c *cHello) Hello(ctx context.Context, req *apiv1.HelloReq) (res *apiv1.HelloRes, err error) { g.RequestFromCtx(ctx).Response.Writeln("Hello World!") return }
这种绑定形式,只是内容获取需要先解密,解密后才能拿到json字符串s.Group("/", func(group *ghttp.RouterGroup) { group.Bind( new(Hello), ) })
//use middleware func for routerfunc (s *sMiddleware) DecodeData(r *ghttp.Request) { data := r.Get("data", "").String()//replac your param key if data != "" { dataStr, err := gbase64.DecodeToString(data)//replac your decode func if err == nil && dataStr != "" { dataMap := gjson.New(dataStr).Map() //r.SetParamMap(dataMap) for key, val := range dataMap { r.SetQuery(key, val) //r.SetForm(key, val) } } } r.Middleware.Next()}
感谢,确实可以
一个接口应当只做一件事情,HTTP Method是有意义的,一个接口支持多种HTTP Method方式是接口设计不合理,在规范路由下不支持。建议重新审视接口设计。
HTTP Method
以上说法岂不是说Restful的设计有问题吗?为啥说一个接口支持多种`http Method`方式时不合理的呢?
不是RESTful有问题,是API定义有问题,一个CURD接口在RESTful实现应当有4-5个API定义,实现不同的业务逻辑。
RESTful
CURD
4-5
例如,拿用户接口来讲,可能存在以下API定义的RESTful接口:
创建用户 PUT /user
用户列表 GET /user
用户详情 GET /user/{uid}
修改用户 POST /user/{uid}
删除用户 DELETE /user/{uid}
不存在一个API绑定多个HTTP Method的场景。我理解这应该是开发基础啊。
哦哦,我理解的是`/user`算一个接口。
同样的疑问: 一个接口应当只做一件事情,HTTP Method是有意义的,一个接口支持多种HTTP Method方式是接口设计不合理,在规范路由下不支持REST 风格?
不是这个意思,可能文档描述有混淆,我更新了一下。
有个比较别扭的是规范路由在controller中时如何判断请求参数是否存在?比如,获取用户列表接口 /user/list ,现在加一个星标用户的筛选(即:(1)返回无论有无星标的所有用户:/user/list,(2)返回无星标用户:/user/list?star=0,(3)返回有星标用户:/user/list?star=1)。由于golang的基本类型没有空值的定义,无论将star定义为bool还是int,在controller中读取到star为0时,无法分辨是否是golang的默认值,也就分辨不出是第一还是第二种情况。再调用ghttp.Request来判断的话感觉失去使用规范路由的意义和便利性。我现在临时做法是把无星标的请求设为/user/list?star=2,然后在向数据库请求时候需要在controller再转换一次,太麻烦。
/user/list
/user/list?star=0
/user/list?star=1
/user/list?star=2
这个问题在字符串类型参数中也存在,无法分辨是真的空字符串还是前端没有传这个参数
定义为指针类型
和用ghttp.Request类似,失去使用规范路由的意义和便利性
定义为指针后未传参数的情况下为nil, star *int 即 star==nil 为未传, struct成员定义为非指针类型是具有默认值这是golang本身的特性.int=>0 bool=>false string=>""
https://github.com/gogf/gf/blob/555bb3fa6b465b9cb201d1428861e20225dc2681/net/goai/goai_shema.go#L246
这个里面 有一个 isAllEnumNumber 的判断,这样的话,在校验规则里面,如果写 in:00,01 在导出的api 提示 的enum 中,会改成 0 和 1 数字形式.
能否改成纯字符串,不要弄一个 纯数字的转换呢?
66 Comments
mtgnorton
请教一下,现在可以做到在swagger接口页面全局设置header头的鉴权字段么
beautiful
我试了是支持的。 goai里面的结构体对应的就是openApi3官网的yaml结构.
mtgnorton
感谢
白夜
beautiful mtgnorton
代码加上了,swagger页面上出现了Authorize按钮,设置key之后,使用try it out 发出的请求并没有在header带上token。 怎么回事呢?
白夜
经过研究发现,
openapi.Components
配置SecuritySchema
之后只是让swagger
定义了一个校验的方式,并没有让每一个API
使用这个校验,必须在每一个path
上配置上这个校验,才能真正生效。但是发现gf
并没有支持这个功能,经过修改gf
的代码,实现了该效果:swagger_ui.png (1217×599) (smartbear.co) 类似于这个图上的 那个Authorize
按钮和每个API
后边的那个锁图标,实际体验可以看 Swagger UI 这个demo
的apiKey
方式。我实现的方式为:
SecuritySchemes
修改我本地的
E:\go-workspace\pkg\mod\github.com\gogf\gf\v2@v2.0.0-rc3\protocol\goai\goai_path.go
文件中的91行,把option
的初始化改为:此时再看
swaggerUI
页面就可以看到那个Authorize
按钮和每个API
后边的那个锁图标。使用try it out
按钮也可以实现在header
上自动加上想要的token
。郭强 海亮 gf是否有更好的方式支持,而不是我这样修改
gf
的源码?郭强
这个只是
OpenAPI
接口定义的展示而已,真正要实现功能还是得依靠中间件。关于全局设置
OpenAPI
属性,可以Server.GetOpenAPI
后修改goai.OpenAPI
对象对应属性即可,不用修改源码。focus-single
项目示例代码有例子:https://github.com/gogf/focus-single/blob/786c16e7516dd68c11352cc4fce3152353c20c60/internal/cmd/cmd.go#L110白夜
首先,全局设置OpenAPI属性的确可以使用Server.GetOpenAPI后修改goai.OpenAPI,但是我这里的需求是每一个api的path对应的swagger定义,不是全局的,所以这里提供的方法是无效的。
另外,无论是中间件也好,hook也好,都是request--》response 的流程过程中进行拦截处理,而我这里的诉求是在server启动之后,生成openAPI的定义时候触发。所以,中间件不行。
目前只能改gf的源码。请仔细看我的问题描述
丑的别致
删除
海亮
总结后分享到这里常见问题(FAQ)
丑的别致
分享规范化路由学习笔记
王俊玺
强哥,自动生成的 swagger 页面中,【Responses】栏只列出了 200 状态。
[假装有截图]
是否有办法能自定义每个路由的 400、401、403、500 错误呢?
或者为所有路由配置统一的 400、401、403、500 错误。
郭强
这个只有自己获取
Server
的OpenApi
对象后自己去扩展了,无法在Req
对象中通过结构体标签绑定,因为那样太复杂了,可维护性太低。丑的别致
http://gf.l11.cn/ 规范化路由代码生成
郭强
你这有点意思哦。
黄骞
你这个是真的棒...点赞
丑的别致
https://gitee.com/Guwengo/gf_code_auto
基于后端 结构体 自动生成CURD代码的版本来了
基于GF自己的模板引擎制作
更方便
更便捷
强仔
gf 工具里面应该集成这个功能,模板能定义最好,起码把该有的文件给创建了.哈哈
youxue2016
swagger ui在使用gf-user-demo时,没有try it out按钮哦
皛心
关于goframe2.0规范路由的个人见解
白夜
使用v2.0.1版本及以上版本会发现 swaggerUI被修改了为 redoc了。redoc缺少了 Try it console。能不能提供一个方式,可以选择swaggerUI或者redoc 么?
郭强
可以自己开个静态页面展示自己的
SwaggerUI
,然后仅使用Server
的OpenAPI
地址。卡卡
灵活性太受限了
比如一个接口,可能有多个路由,但入参结构体相同,应如何处理呢?
郭强
一接口多路由:参考常见问题。
请求参数复用:将公用的结构体进行嵌套复用。
卡卡
指这个吗 “ 1、在规范路由下,同一接口如何支持多种HTTP Method提交方式 ”
我的意思是,/api/hello, /welcome/sayhello, 两个路由地址,可能指向同一个 handler (如 Tom.SayHello())
郭强
规范路由要求会比较严格一些,"规范"二字由此而来。你描述的
case
已经不太规范了,但你可以通过两种方式来实现:1、适当规范你的路由设计,使用不同的路由前缀来区分不同的业务模块。这样你定义的输入输出结构体不用重新定义,只需要在路由注册的时候使用分组路由,绑定不同的路由前缀。
2、定义不同的
Req
结构体,内部嵌套相同的结构体来实现。sanrentai
如果希望自定义response 该如何处理,比如 code 为 string 类型,
不同的分组路由,使用不一样的response。 历史遗留系统,返回样式五花八门
张文杰
请教一下,新版本的路由注册,我有点迷,普通的用法我会
比如我发送 GET 和 PUT 请求,是 user/:id ,那么 g.Meta 里面的 path 标签应该如何写呢?
如果我打算把参数放在路径里面,不通过 struct 里面的其它属性来定义,我该如何在控制器中获取到这个 :id 呢?
我用了
好像获取不到
白夜
无论参数是request body还是url上的,都需要在结构体里定义。
张文杰
确实取到值了,大哥你好聪明啊,我读完文档,没找到相关用法,谢谢!
canyonwan
这个我在文档的确看到了 是需要在 g.Meta的tag里写
canyonwan
接口文档-OpenAPIv3
在 三、常用协议标签的表格里
张文杰
我又遇到了一个新的疑问
这里不能是 Id 否则获取到的就是个莫名其妙的数值,我传的 Id 是2,但是获取到的是下面的 13
如果把 Id 改成 RoleId ,就可以正确获取到值,这是为什么呢?
写成下面就是正常的,这是规定吗?
张文杰
问题已解决,补充一下这个答案。
一位朋友提示会不会是中间件赋值的影响
我在断点调试的过程中发现了 ID 被覆盖了
原因是 JWT 中 IdentityKey 我用了 id 这个作为 key
如果替换成一个其它的字段,就不会影响前端业务字段了
鼻屎拌饭加蛋
可能我的理解级别不够,分组路由不挺好吗,为什么非要卷出一个规范路由,这所谓的规范,反正让我背这一串字符串,挺难,接口上百个,感觉这字符串难维护,比如:`path:"/user/{uuid}" method:"put" `
郭强
不同场景,选择适合的就好。
石小志
对于这种规范路由的方式,如果返回的格式不同,是不是就不能用了?比如想下面两种格式。如果能用的话,统一返回值处理那里应该怎么做?
糖水不加糖
重写MiddlewareHandlerResponse 根据业务需要去处理返回内容.
糖水不加糖
另外 建议将业务内容包到data内部保持风格一致.
郑龙
请教一下,请求结构体中的参数从 http header 获取参数的情况,使用 in:"header" 是否可以直接获取值。
我本地测试发现不行,不知是框架暂时不支持还是我使用姿势不正确,望可以解答。谢谢。
糖水不加糖
还没实现这个标签 先用手动获取赋值处理吧.
郑龙
感谢。现在是直接由ctx,从header里取的。
糖水不加糖
auth在控制器处理的话复用效率比较低,一般在前置中间件中处理,而中间件取header数据也是从request对象取,其实并不冲突.
小鹿
两个问题
simonchyi
ctrl & logic 层可以拿到RoleUpdateReq,通过反射就能拿 tags/methmod...
小鹿
我想是现在中间层,在请求处理前进行统一处理,也就是在controller层前一层处理掉没有登录的请求,并且返回统一的响应值,按照你的说话,可能我需要在进去在处理,那每一个函数都要有自己的鉴权处理,我觉得可能有一些麻烦
zspmhzx
我也是想这样,之前看到你问的这个,自己也研究了,没找到办法。后面调试的时候,无意中看到ghttp.Request有个
GetServeHandler方法,可以拿到路由注册的controller函数,而req这个结构体就是函数的第二个参数。因此可以通过反射得到gmeta信息。具体方法如下:
yidashi
原谅我吐槽一下,这个api结构体的字段tag都有哪些,从截图里我看到了dc是字段描述,好歹文档提一嘴吧
JWpang
接口文档-OpenAPIv3
接着往下看就有了
yidashi
好嘞,多谢
yidashi
我想出一个前台接口文档,一个后台接口文档,同一个项目,应该怎么弄
郭强
Server
不同的监听端口。Server
相同的监听端口但不同的URI。这个算高级用法,可以看下Server
中有个SetListener
方法。小鹿
有一个问题, 设置参数 in:query 但是还是从请求体里获取的 那设置这个的必要性在哪呢,这个并不是从query取得值
allen
规范路由下预检OPTIONS请求怎么通过;
规范路由只定义了post方法;
发起预检请求直接返回404 not found了,没有进到cors中间件
陈鹏
请问密文请求,解密后如何按现在的规范传入这种结构呢
糖水不加糖
陈鹏
感谢,确实可以
山辣
一个接口应当只做一件事情,
HTTP Method
是有意义的,一个接口支持多种HTTP Method
方式是接口设计不合理,在规范路由下不支持。建议重新审视接口设计。以上说法岂不是说Restful的设计有问题吗?为啥说一个接口支持多种`http Method`方式时不合理的呢?
郭强
不是
RESTful
有问题,是API
定义有问题,一个CURD
接口在RESTful
实现应当有4-5
个API
定义,实现不同的业务逻辑。例如,拿用户接口来讲,可能存在以下API定义的RESTful接口:
创建用户 PUT /user
用户列表 GET /user
用户详情 GET /user/{uid}
修改用户 POST /user/{uid}
删除用户 DELETE /user/{uid}
不存在一个
API
绑定多个HTTP Method
的场景。我理解这应该是开发基础啊。山辣
哦哦,我理解的是`/user`算一个接口。
randix
同样的疑问: 一个接口应当只做一件事情,
HTTP Method
是有意义的,一个接口支持多种HTTP Method
方式是接口设计不合理,在规范路由下不支持REST 风格?郭强
不是这个意思,可能文档描述有混淆,我更新了一下。
a
有个比较别扭的是规范路由在controller中时如何判断请求参数是否存在?比如,获取用户列表接口
/user/list
,现在加一个星标用户的筛选(即:(1)返回无论有无星标的所有用户:/user/list
,(2)返回无星标用户:/user/list?star=0
,(3)返回有星标用户:/user/list?star=1
)。由于golang的基本类型没有空值的定义,无论将star定义为bool还是int,在controller中读取到star为0时,无法分辨是否是golang的默认值,也就分辨不出是第一还是第二种情况。再调用ghttp.Request来判断的话感觉失去使用规范路由的意义和便利性。我现在临时做法是把无星标的请求设为/user/list?star=2
,然后在向数据库请求时候需要在controller再转换一次,太麻烦。这个问题在字符串类型参数中也存在,无法分辨是真的空字符串还是前端没有传这个参数
糖水不加糖
定义为指针类型
a
和用ghttp.Request类似,失去使用规范路由的意义和便利性
糖水不加糖
定义为指针后未传参数的情况下为nil, star *int 即 star==nil 为未传, struct成员定义为非指针类型是具有默认值这是golang本身的特性.int=>0 bool=>false string=>""
小兵张嘎
https://github.com/gogf/gf/blob/555bb3fa6b465b9cb201d1428861e20225dc2681/net/goai/goai_shema.go#L246
这个里面 有一个 isAllEnumNumber 的判断,这样的话,在校验规则里面,如果写 in:00,01 在导出的api 提示 的enum 中,会改成 0 和 1 数字形式.
能否改成纯字符串,不要弄一个 纯数字的转换呢?