This commit is contained in:
Tiger Wang 2022-07-07 16:21:22 -04:00
parent 9cf515b113
commit e2a41e5734
2 changed files with 23 additions and 8 deletions

View File

@ -75,22 +75,39 @@ func InitRouter() *gin.Engine {
v1UserGroup.GET("/info", v1.GetUserInfo) v1UserGroup.GET("/info", v1.GetUserInfo)
// @tiger - RESTful 规范下所有对 user 的写操作,都应该 POST /v1/user/:id // @tiger - RESTful 规范下所有对 user 的写操作,都应该 POST /v1/user/:id
// - 不需要每个更改的属性建一个 API
v1UserGroup.PUT("/username", v1.PutUserName) v1UserGroup.PUT("/username", v1.PutUserName)
v1UserGroup.PUT("/password", v1.PutUserPwd) v1UserGroup.PUT("/password", v1.PutUserPwd)
v1UserGroup.PUT("/nick", v1.PutUserNick) // 改成 /nickname v1UserGroup.PUT("/nick", v1.PutUserNick) // 改成 /nickname
v1UserGroup.PUT("/desc", v1.PutUserDesc) // 改成 /description v1UserGroup.PUT("/desc", v1.PutUserDesc) // 改成 /description
// @tiger - RESTful 规范下应该是 GET /v1/users/?username=xxxx // @tiger - RESTful 规范建议是 GET /v1/users/?username=xxxx
// 这是一个查询 API返回一个 users 数组(即使 username 是唯一的)
// 之所以不用 /v1/user/:username 是因为和 /v1/user/:id 路由冲突
//
// 当前这个设计的问题是GET 不应该同时接收 request body。
// GET 方法应该只接收 URL 参数
v1UserGroup.GET("/info", v1.GetUserInfoByUserName) v1UserGroup.GET("/info", v1.GetUserInfoByUserName)
// @tiger - 改成 /user/current/custom/... 和上面的 current 对应
// 如果未来想获得其它用户的 custom 数据,可以用 /v1/user/:id/custom/... 来保持统一
v1UserGroup.GET("/custom/:key", v1.GetUserCustomConf) v1UserGroup.GET("/custom/:key", v1.GetUserCustomConf)
v1UserGroup.POST("/custom/:key", v1.PostUserCustomConf) v1UserGroup.POST("/custom/:key", v1.PostUserCustomConf)
v1UserGroup.DELETE("/custom/:key", v1.DeleteUserCustomConf) v1UserGroup.DELETE("/custom/:key", v1.DeleteUserCustomConf)
// @tiger - 下面这两个 API 从感知上很难区分。
// 如果前者是负责上传,后者负责指定的话,那么
// 前者应该用一个统一的和目的无关的用户文件上传 API而不是针对 image file 的
v1UserGroup.POST("/upload/image/:key", v1.PostUserUploadImage) v1UserGroup.POST("/upload/image/:key", v1.PostUserUploadImage)
v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage) v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
v1UserGroup.DELETE("/image", v1.DeleteUserImage) v1UserGroup.DELETE("/image", v1.DeleteUserImage)
// @tiger - 应该用上面提到的统一的文件上传 API 先上传头像文件,然后
// 用类似上面第二个 API 的方式指定头像文件。这样整体 API 体验更加统一。
v1UserGroup.PUT("/avatar", v1.PutUserAvatar) v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
v1UserGroup.GET("/avatar", v1.GetUserAvatar) v1UserGroup.GET("/avatar", v1.GetUserAvatar)
// @tiger - 删除用户直接用 DELETE /v1/user/:id不需要在路径中用谓语
v1UserGroup.DELETE("/delete/:id", v1.DeleteUser) v1UserGroup.DELETE("/delete/:id", v1.DeleteUser)
} }

View File

@ -36,12 +36,6 @@ func PostUserRegister(c *gin.Context) {
username := json["user_name"] username := json["user_name"]
pwd := json["password"] pwd := json["password"]
// @tiger - POST 方法尽量统一用 JSON 本体来传参。用 query string 来传参的话,
// 1 - 有可能会被路由记录,形成不必要的泄露(这里假设 key 是关键信息)
// 2 - 开发者不需要处理两种入参方式
//
// query string 更加适合 GET 读操作,或者运维层面的需求,比如跟踪码,回调地址等
key := c.Param("key") key := c.Param("key")
if _, ok := service.UserRegisterHash[key]; !ok { if _, ok := service.UserRegisterHash[key]; !ok {
c.JSON(http.StatusOK, c.JSON(http.StatusOK,
@ -353,6 +347,9 @@ func GetUserInfo(c *gin.Context) {
// @Router /user/info [get] // @Router /user/info [get]
func GetUserInfoByUserName(c *gin.Context) { func GetUserInfoByUserName(c *gin.Context) {
json := make(map[string]string) json := make(map[string]string)
// @tiger 当前这个设计的问题是GET 不应该同时接收 request body。
// GET 方法应该只接收 URL 参数
c.BindJSON(&json) c.BindJSON(&json)
userName := json["user_name"] userName := json["user_name"]
if len(userName) == 0 { if len(userName) == 0 {
@ -415,6 +412,7 @@ func GetUserCustomConf(c *gin.Context) {
return return
} }
filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json" filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json"
data := file.ReadFullFile(filePath) data := file.ReadFullFile(filePath)
if !gjson.ValidBytes(data) { if !gjson.ValidBytes(data) {
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
@ -469,7 +467,7 @@ func DeleteUserCustomConf(c *gin.Context) {
return return
} }
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json" filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json"
os.Remove(filePath) os.Remove(filePath) // @tiger - 这里万一无法实际删除,后面仍然有可能返回成功
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }