利用gorilla/mux区分数据类型
"github.com/gorilla/mux"
func handleVersion(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hi, this is an http verison")
vars := mux.Vars(req)
fmt.Printf("%v", vars)
category := vars["format"]
fmt.Printf("%v", category)
query := req.URL.Query()
fmt.Printf("%v", query)
Format := req.URL.Query()["format"]
fmt.Printf("%v", Format)
}
func mainmux() {
routes := mux.NewRouter()
routes.HandleFunc("/api.{format:json|xml|txt}/usert", handleVersion).Methods("Get")
http.Handle("/", routes)
http.ListenAndServe(":8080", nil)
}
可以在handler中根据format来对传入的数据进行不同解码方法。
利用jas
https://github.com/coocood/jas/blob/master/README_ZH.md
https://godoc.org/github.com/coocood/jas
特性
无需手动定义URL路由规则, 路由规则由资源struct名和方法名决定,保证了方法名和URL路径的一致性。
生成所有已处理的URL路径,用”\n”分割,可以作为API参考资料或检测API的改变。
非侵入式,JASrouter只是一个http.Handler,可以和其他http.Handler一起使用,或在一个服务端口使用用多个JAS router。
支持HTTP Streaming, 可以保持长连接,向客户端发送实时数据,并在客户端关闭时得到通知。
支持从JSON request body的任意深度的路径提取参数,可以像JSON RPC一样用。
提取参数的同时进行基本的验证,支持验证整数,string的长度,string的rune长度,string正则匹配。
如果验证失败,响应默认的包含参数名的消息,(可选)将错误用Common Log Format写入日志。
把未处理的错误包装成InternalError类型,响应默认消息,将stacktrace和请求信息用Common Log Format写入日志,支持自定义的错误回调函数。
错误使用interface类型,这样当自带的错误类型不能满足需求,可以自定义错误类型。
支持gzip。
丰富的配置选项。
第一条中,路由规则由struct名和方法名定义,参考如下样例
type Users struct {}
func (*Users) Photo (ctx *jas.Context) {} // `GET /users/photo`
func (*Users) PostPhoto (ctx *jas.Context) {} // `POST /users/photo`
func (*Users) PostPost (ctx *jas.Context) {} // `POST /users/post`
func (*Users) GetPost (ctx *jas.Context) {} // `GET /users/post`
func (*Users) PutPhoto (ctx *jas.Context) {} // `PUT /users/photo`
func (*Users) DeletePhoto (ctx *jas.Context) {} // `DELETE /users/photo`
可以看到,Users对应路径users,各个方法名对应子路径,并且方法名称的前缀Post,Get,Put,Delete对应HTT请求POST,GET,PUT,DELETE,如果不指定前缀的话,则默认对应GET的HTTP请求。这样的struct类型称为resource。
当应用启动的时候,可以将多个resouce传递给 jas.NewRouter得到一个jas.Router .
router := jas.NewRouter(new(Users), new(Posts), new(Photos)
然后可以对其进行配置:
router.BasePath = "/v1/"
router.EnableGzip = true
获取所有handle的路径:
fmt.Println(router.HandledPaths(true)) // true for with base path. false for without base path.
设置路由和监听:
http.Handle(router.BasePath, router)
http.ListenAndServe(":8080", nil)
完整样例:
import "github.com/coocood/jas"
type Hello struct{}
func (*Hello) Get(ctx *jas.Context) {
ctx.Data = "helloworld"
}
func main() {
route := jas.NewRouter(new(Hello))
route.BasePath = "/v1/"
fmt.Println(route.HandledPaths(true))
http.Handle(route.BasePath, route)
http.ListenAndServe(":8080", nil)
}
路径中添加id
如果给resource的名字后面带上Id的后缀,那么在生成的路径,resouce名称和method名称的路径中间会多一个id的路径,这个id可以通过ctx.Id获取。
type UsersId struct {}
func (*UsersId) Photo (ctx *jas.Context) {// `GET /users/:id/photo`
id := ctx.Id
_ = id
}
完整样例
type Hello struct{}
func (*Hello) Get(ctx *jas.Context) {
ctx.Data = "helloworld"
}
type UserId struct{}
func (*UserId) Photo(ctx *jas.Context) { // `GET /users/:id/photo`
id := ctx.Id
ctx.Data = id
fmt.Println(id)
}
func main() {
route := jas.NewRouter(new(Hello), new(UserId))
route.BasePath = "/v1/"
fmt.Println(route.HandledPaths(true))
http.Handle(route.BasePath, route)
http.ListenAndServe(":8080", nil)
}
GET /v1/hello
GET /v1/user/:id/photo
33
获取请求的值
jas含有许多方法获取请求数据的值,可以分为两类,以Find开头的方法和以Require开头的方法。当请求的参数无效时,以Find开头的方法会返回error,而以Require开头的方法会终止方法的执行并且相应错误信息。
https://godoc.org/github.com/coocood/jas里面 Users的方法是Photo,POST数据时一直提示404,应该更改为PostPhoto
func (*Users) Photo (ctx *jas.Context) {
// will stop execution and response `{"data":null,"error":"nameInvalid"} if "name" parameter is not given..
name := ctx.RequireString("name")
age := ctx.RequirePositiveInt("age")
grade, err := ctx.FindPositiveInt("grade")
// 6, 60 is the min and max length, error message can be "passwordTooShort" or "passwordTooLong"
password := ctx.RequireStringLen(6, 60, "password")
// emailRegexp is a *regexp.Regexp instance.error message would be "emailInvalid"
email := ctx.RequireStringMatch(emailRegexp, "email")
_, _, _, _, _, _ = name, age, grade, err,password, email
}
完整测试代码,注意要
type Users struct{}
func (*Users) PostPhoto(ctx *jas.Context) {
fmt.Println("begin")
name := ctx.RequireString("name")
fmt.Println(name)
age := ctx.RequirePositiveInt("age")
fmt.Println(age)
grade, err := ctx.FindPositiveInt("grade")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(grade)
password := ctx.RequireStringLen(6, 60, "password")
fmt.Println(password)
// email := ctx.RequireStringMatch(ema)
}
func main() {
route := jas.NewRouter(new(Hello), new(UserId), new(Users))
route.BasePath = "/v1/"
fmt.Println(route.HandledPaths(true))
http.Handle(route.BasePath, route)
http.ListenAndServe(":8080", nil)
}