# HTTP 注入说明

# HTTP 依赖注入标签的格式

${attributeName} ${attributeType} gone:"http,${kind}=${key}"

举例:

router.GET("/search", function(in struct{
    selects []int `gone:"http,query=select"`
}){
    //注入值in.selects为`[]int{1,2,3}`
    fmt.Printf("%v", in.selects)
})

上面例子中,

  • selects为属性名(attributeName);
  • []int为属性类型(attributeType);
  • query为注入类型(kind);
  • select为注入键值(key)。

# 支持注入的类型和响应标签

名称 属性类型${attributeType} 注入类型${kind} 注入键值${key} 说明
上下文注入 gone.Context / / (不推荐)注入gin请求上下文对象,不需要类型${kind}和键值${key}
上下文注入 *gone.Context / / (推荐)注入gin请求上下文指针,不需要类型${kind}和键值${key}
请求注入 http.Request / / 不推荐)注入http.Request对象,不需要类型${kind}和键值${key}
请求注入 *http.Request / / (推荐)注入http.Request指针,不需要类型${kind}和键值${key}
地址注入 url.URL / / (不推荐)注入url.URL,不需要类型${kind}和键值${key}
地址注入 *url.URL / / (推荐)注入url.URL指针,不需要类型${kind}和键值${key}
请求头注入 http.Header / / (推荐)注入http.Header(请求头),不需要类型${kind}和键值${key}
响应注入 gone.ResponseWriter / / 注入gin.ResponseWriter(用于直接写入响应数据),不需要类型${kind}和键值${key}
Body注入 结构体、结构体指针 body / body注入;将请求body解析后注入到属性,注入类型为 body,不需要“注入键值${key}”;框架根据Content-Type自动判定是json还是xml等格式;每个请求处理函数只允许存在一个body注入
请求头单值注入 number | string header 缺省取字段名 以键值${key}key获取请求头,属性类型支持 简单类型[1],解析不了会返回参数错误
URL路径参数注入 number | string param 缺省取字段名 以“注入键值${key}”为key调用函数ctx.Param(key)获取Url中定义的参数值,属性类型支持 简单类型[1],解析不了会返回参数错误
Query参数注入 number | string | []number | []string | 结构体 | 结构体指针 query 缺省取字段名 以“注入键值${key}”为key调用函数ctx.Query(key)获取Query中的参数,属性类型支持 简单类型[1]支持简单类型的数组,支持结构体和结构体指针,解析不了会返回参数错误
Cookie注入 number | string cookie 缺省取字段名 以“注入键值${key}”为key调用函数ctx.Context.Cookie(key)获取Cookie的值,属性类型支持 简单类型[1],解析不了会返回参数错误

# Query参数注入

# 属性类型为简单类型[1]

解析不了会返回参数错误。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				yourName string `gone:"http,query=name"` //注册请求query中的name参数
				name string `gone:"http,query"` //注册请求query中的name参数;不指定参数名,则取属性名作为参数名
                age int `gone:"http,query=age"` //int类型
			}) string {
				return fmt.Sprintf("hello, %s, your name is %s", in.yourName, in.name)
			},
		)

# 属性类型为简单类型的数组

解析不了会返回参数错误。 下面代码,query为?keyword=gone&keyword=is&keyword=bestin.keywords的值将会为 []string{"gone","is","best"}

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				keywords []string `gone:"http,query=keyword"` //简单类型的query数组参数注入
			}) string {
				return fmt.Sprintf("hello, keywords is [%v]", in.keywords)
			},
		)

# 属性类型为结构体或者结构体指针

这种类型key无需指定;假设query为?page=1&pageSize=20&keyword=gone&keyword=is&keyword=bestin.req的值将会为 {1,20,[]string{"gone","is","best"}};注意结构体中可以使用form标签进行属性映射。

解析不了会返回参数错误。

	type Req struct {
		Page     string   `form:"page"`
		PageSize string   `form:"pageSize"`
		Keywords []string `form:"keywords"`
	}
	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				req Req `gone:"http,query"`
                req2 *Req `gone:"http,query"`
			}) string {
				fmt.Println(in.req)
				return fmt.Sprintf("hello, keywords is [%v]", in.req.Keywords)
			},
		)

# URL路径参数注入

URL 路径参数,是指定义在URL路由中的参数,注入属性的类型支持stringint,uint,float64等数字类型,解析不了会返回参数错误。如下:

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello/:name", //url中定义参数名为name
			func(in struct {
				name string `gone:"http,param"` //不指定参数名,使用属性名作为参数名
				name2 string `gone:"http,param=name"` //使用key指定参数名
			}) string {
				return "hello, " + in.name
			},
		)

# Body注入

Body注入,是指读取HTTP请求正文内容,解析成结构体,注入属性的类型支持结构体、结构体指针,解析不了会返回参数错误。

支持多种ContentType:json、xml、form-data、form-urlencoded等,不传ContentType时,默认为application/x-www-form-urlencoded。

结构体可以使用form标签进行form-data、form-urlencoded的属性映射;xml标签进行xml的属性映射;json标签进行json的属性映射。

具体规则可以参考:gin#Model binding and validation (opens new window)

举例如下:

	type Req struct {
		Page     string   `form:"page" json:"page,omitempty" xml:"page" binding:"required"`
		PageSize string   `form:"pageSize" json:"pageSize,omitempty" xml:"pageSize" binding:"required"`
		Keywords []string `form:"keywords" json:"keywords,omitempty" xml:"keywords" binding:"required"`
	}
	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				req Req `gone:"http,body"`  //注意:body只能被注入一次,因为 writer被读取后就变成空了
				// req2 *Req `gone:"http,body"`
			}) string {
				fmt.Println(in.req)
				return fmt.Sprintf("hello, keywords is [%v]", in.req.Keywords)
			},
		)

# 请求头注入

HTTP请求头注入,用于获取某个请求头信息,注入属性的类型支持stringint,uint,float64等数字类型,解析不了会返回参数错误。 比如下面代码,可以用于读取请求头中的Content-Type信息。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				contentType string `gone:"http,header"` //不指定参数名,使用属性名作为参数名
				contentType2 string `gone:"http,header=contentType"` //使用key指定参数名
			}) string {
				return "hello, contentType = " + in.contentType
			},
		)

# Cookie注入

Cookie注入,用于获取某个cookie信息,注入属性的类型支持stringint,uint,float64等数字类型,解析不了会返回参数错误。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				token string `gone:"http,cookie"` //不指定参数名,使用属性名作为参数名
				token2 string `gone:"http,header=token"` //使用key指定参数名
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 高级

另外,我们还支持几种特殊结构体(或结构体指针、接口、map)的注入,由于golang的“值拷贝”推荐使用指针注入,这些结构体代表了HTTP请求、响应、上下文等,这些结构体的注入不需要指定kindkey

# URL结构体注入

支持属性类型为 url.URL 或者 *url.URL,该类型定义在net/url包中,代表了HTTP请求的URL。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				url *url.URL `gone:"http"` //使用结构体指针
				url2 url.URL `gone:"http"` //使用结构体
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 请求头注入

支持属性类型为 http.Header,该类型定义在net/http包中,代表了HTTP请求的Header。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				header http.Header `gone:"http"`
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 上下文结构体注入

支持属性类型为 gin.Content 或者 *gin.Content,该类型定义在github.com/gin-gonic/gin包中,代表了HTTP请求的上下文。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				context *gin.Content `gone:"http"` //使用结构体指针
				context2 gin.Content `gone:"http"` //使用结构体
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 请求结构体注入

支持属性类型为 http.Request 或者 *http.Request,该类型定义在net/http包中,代表了HTTP请求信息。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				request *http.Request `gone:"http"` //使用结构体指针
				request2 http.Request `gone:"http"` //使用结构体
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 请求响应接口注入

支持属性类型为 gin.ResponseWriter,该类型定义在github.com/gin-gonic/gin包中,代表了HTTP响应信息,可以使用该接口响应请求信息。

	ctr.rootRouter.
		Group("/demo").
		POST(
			"/hello",
			func(in struct {
				writer gin.ResponseWriter `gone:"http"`
			}) string {
				return "hello, your token in cookie is" + in.token
			},
		)

# 备注

[1]. 简单类型指 字符串、布尔类型 和 数字类型,其中数字类型包括:

  • 整数类型:int、uint、int8、uint8、int16、uint16、int32、uint32、int64、uint64
  • 非负整数类型:uint、uint8、uint16、uint32、uint64
  • 浮点类型:float32、float64