Gin框架
请求
获取请求参数
go
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/example", func(c *gin.Context) {
// 使用c.Query()方法获取参数值
paramValue := c.Query("paramName")
// 使用c.DefaultQuery()方法获取参数值,如果参数不存在,设置默认值
defaultParamValue := c.DefaultQuery("defaultParamName", "defaultValue")
c.String(200, "ParamValue: %s; DefaultParamValue: %s", paramValue, defaultParamValue)
})
router.Run(":8080")
}
从uri中绑定参数到struct
MustBind
和ShouldBind
的区别:MustBind
在失败后,会自动调用AbortWithError(400)
,代码无法再自定义返回错误,ShouldBind
在绑定失败后不会设置响应,而是返回错误。如果希望手动管理响应,使用后者。
validator:Package validator
go
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
// Example for binding JSON ({"user": "manu", "password": "123"})
router.POST("/loginJSON", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if json.User != "manu" || json.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
// Example for binding XML (
// <?xml version="1.0" encoding="UTF-8"?>
// <root>
// <user>manu</user>
// <password>123</password>
// </root>)
router.POST("/loginXML", func(c *gin.Context) {
var xml Login
if err := c.ShouldBindXML(&xml); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if xml.User != "manu" || xml.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
// Example for binding a HTML form (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
var form Login
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if form.User != "manu" || form.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
获取请求URL
go
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/example", func(c *gin.Context) {
// 获取完整的URL
fullURL := c.Request.URL.String()
c.String(200, "Full URL: %s", fullURL)
})
router.Run(":8080")
}
获取请求body
在Go语言的Gin框架中,要将请求的body打印出来,你可以使用以下代码:
go
package main
import (
"bytes"
"fmt"
"github.com/gin-gonic/gin"
"io/ioutil"
)
func main() {
r := gin.Default()
r.POST("/", func(c *gin.Context) {
// 读取请求的body
bodyBytes, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.String(400, "请求body读取错误: %v", err)
return
}
// 打印请求的body
fmt.Println(string(bodyBytes))
// 将读取后的body重新写回
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
c.String(200, "请求body已打印")
})
r.Run(":8080")
}
这个例子中,我们创建了一个简单的Gin服务器,监听POST请求。在这个请求处理函数中,我们读取请求的body,将其转换为字符串并打印出来。然后,我们将读取后的body重新写回,以便其他中间件或处理函数可以继续使用它。
响应
如何把http.Response对象作为gin的响应
要将http.Response对象的内容作为Gin框架的响应,可以将http.Response对象的StatusCode、Header和Body分别设置为Gin上下文(*gin.Context)的响应状态码、响应头和响应体。
以下是一个例子:
go
package main
import (
"io"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/proxy", func(c *gin.Context) {
// 发送请求并获取http.Response对象
response, err := http.Get("http://example.com")
if err != nil {
c.String(http.StatusInternalServerError, "Error making request: %v", err)
return
}
defer response.Body.Close()
// 将http.Response的状态码设置为Gin响应的状态码
c.Status(response.StatusCode)
// 将http.Response的Header设置为Gin响应的Header
for key, values := range response.Header {
for _, value := range values {
c.Header(key, value)
}
}
// 将http.Response的Body设置为Gin响应的Body
io.Copy(c.Writer, response.Body)
})
router.Run(":8080")
}
在这个例子中,我们创建了一个Gin路由,当访问/proxy时,会发送一个请求到http://example.com,然后将收到的http.Response对象的内容作为Gin响应返回。
注意,我们使用io.Copy()函数将response.Body复制到Gin上下文的c.Writer中。这样可以避免一次性读取整个响应体到内存,特别是当响应体很大时,这种方式更加高效。
路由
把所有url都路由到一个handler上
go
outer := gin.Default()
outer.Any("/*any", func(c *gin.Context) {
c.String(200, "All URLs are handled by this handler.")
)
实现反向代理
go
func main() {
r := gin.Default()
// 假设你的后端服务地址为:http://localhost:8081
backendURL, err := url.Parse("http://localhost:8081")
if err != nil {
fmt.Println("Error parsing backend URL:", err)
return
}
r.Any("/*path", func(c *gin.Context) {
// 设置需要传递到后端服务的头部信息
c.Request.Header.Set("X-Forwarded-Host", c.Request.Host)
c.Request.Header.Set("X-Forwarded-Proto", c.Request.URL.Scheme)
// 创建一个反向代理处理器
proxy := httputil.NewSingleHostReverseProxy(backendURL)
// 修改请求的URL,使其指向后端服务
c.Request.URL.Path = c.Param("path")
c.Request.URL.RawPath = ""
c.Request.URL.RawQuery = ""
// 通过反向代理处理器处理请求
proxy.ServeHTTP(c.Writer, c.Request)
})
// 监听并在 0.0.0.0:8080 上启动服务
r.Run(":8080")
}