在上一篇文章中我们使用readIn()帮助函数,API服务可以做到对查询参数page和page_size进行校验,如果校验不通过就向客户端返回错误。可以测试下效果:
$ curl "localhost:4000/v1/movies?page=abc&page_size=abc"
{
"error": {
"page": "must be integer value",
"page_size": "must be integer value"
}
}
但是我们还需要对客户端提供的查询字符串值执行一些额外的合法性检查。特别在以下情况:
- page值在1到10,000,000之间
- page_size值在1到100之间
- sort参数只能是所查询内容对应的字段名称。具体来说,在查询movie时,其值可以是:"id", "title", "year", "runtime", "-id", "-title", "-year"和"-runtime"。前面的"-"表示逆序排列查询结果。
要实现上述检查,我们打开internal/data/filters.go文件,并创建ValidateFilters()函数来检查这些值。
我们将跟随前面已使用过的ValidateMovie()模式来实现:
File:internal/data/filters.go
package data
import "greenlight.alexedwards.net/internal/validator"
type Filters struct {
Page int
PageSize int
Sort string
SortSafelist []string
}
func ValidateFilters(v *validator.Validator, f Filters) {
// 检查page和page_size参数
v.Check(f.Page > 0, "page", "must be greater than zero")
v.Check(f.Page < 10_000_000, "page", "must be a maximum of 10 million")
v.Check(f.PageSize > 0, "page_size", "must be greater than zero")
v.Check(f.PageSize <= 100, "page_size", "must be a maximum of 100")
// 检查sort参数,和safelist匹配
v.Check(validator.In(f.Sort, f.SortSafelist...), "sort", "invalid sort value")
}
然后需要更新listMoviesHandler设置SortSafelist字段包含支持的字符串,并调用上面的ValidateFilters()函数。
File:cmd/api/movies.go
package main
...
func (app *application) listMoviesHandler(w http.ResponseWriter, r *http.Request) {
var input struct {
Title string
Genres []string
data.Filters
}
v := validator.New()
qs := r.URL.Query()
input.Title = app.readString(qs, "title", "")
input.Genres = app.readCSV(qs, "genres", []string{})
input.Filters.Page = app.readInt(qs, "page", 1, v)
input.Filters.PageSize = app.readInt(qs, "page_size", 20, v)
input.Filters.Sort = app.readString(qs, "sort", "id")
//检查校验是否通过
if data.ValidateFilters(v, input.Filters); !v.Valid(){
app.failedValidationResponse(w, r, v.Errors)
return
}
//将读取数据返回给客户端
fmt.Fprintf(w, "%+v\n", input)
}
如果你重启服务,并尝试使用不合法的page,page_size和sort参数,你将收到校验不合格的错误响应消息。如下所示:
$ curl "localhost:4000/v1/movies?page=-1&page_size=-1&sort=foo"
{
"error": {
"page": "must be greater than zero",
"page_size": "must be greater than zero",
"sort": "invalid sort value"
}
}
你可以随意使用其他值来测试,直到相信校验都能起作用为止。
查看完整代码,可以阅读【Go web开发】系列文章。









网友评论