自定义 HTTP 配置
直接使用 http.ListenAndServe() ,像这样:
func main() {router := gin.Default()http.ListenAndServe(":8080", router)}
或
func main() {router := gin.Default()s := &http.Server{Addr: ":8080",Handler: router,ReadTimeout: 10 * time.Second,WriteTimeout: 10 * time.Second,MaxHeaderBytes: 1 << 20,}s.ListenAndServe()}
支持 Let’s Encrypt
一个 LetsEncrypt HTTPS 服务器的示例。
package mainimport ("log""github.com/gin-gonic/autotls""github.com/gin-gonic/gin")func main() {r := gin.Default()// Ping 处理器r.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})log.Fatal(autotls.Run(r, "example1.com", "example2.com"))}
自定义 autocert 管理器示例。
package mainimport ("log""github.com/gin-gonic/autotls""github.com/gin-gonic/gin""golang.org/x/crypto/acme/autocert")func main() {r := gin.Default()// Ping handlerr.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})m := autocert.Manager{Prompt: autocert.AcceptTOS,HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"),Cache: autocert.DirCache("/var/www/.cache"),}log.Fatal(autotls.RunWithManager(r, &m))}
使用 Gin 运行多个服务
查看 问题 并尝试下面示例:
package mainimport ("log""net/http""time""github.com/gin-gonic/gin""golang.org/x/sync/errgroup")var (g errgroup.Group)func router01() http.Handler {e := gin.New()e.Use(gin.Recovery())e.GET("/", func(c *gin.Context) {c.JSON(http.StatusOK,gin.H{"code": http.StatusOK,"error": "Welcome server 01",},)})return e}func router02() http.Handler {e := gin.New()e.Use(gin.Recovery())e.GET("/", func(c *gin.Context) {c.JSON(http.StatusOK,gin.H{"code": http.StatusOK,"error": "Welcome server 02",},)})return e}func main() {server01 := &http.Server{Addr: ":8080",Handler: router01(),ReadTimeout: 5 * time.Second,WriteTimeout: 10 * time.Second,}server02 := &http.Server{Addr: ":8081",Handler: router02(),ReadTimeout: 5 * time.Second,WriteTimeout: 10 * time.Second,}g.Go(func() error {return server01.ListenAndServe()})g.Go(func() error {return server02.ListenAndServe()})if err := g.Wait(); err != nil {log.Fatal(err)}}
HTTP2 服务器推送
http.Pusher 仅仅被 go1.8+ 支持。 在 golang 官方博客 中查看详细信息。
package mainimport ("html/template""log""github.com/gin-gonic/gin")var html = template.Must(template.New("https").Parse(`<html><head><title>Https Test</title><script src="/assets/app.js"></script></head><body><h1 style="color:red;">Welcome, Ginner!</h1></body></html>`))func main() {r := gin.Default()r.Static("/assets", "./assets")r.SetHTMLTemplate(html)r.GET("/", func(c *gin.Context) {if pusher := c.Writer.Pusher(); pusher != nil {// 使用 pusher.Push() 去进行服务器推送if err := pusher.Push("/assets/app.js", nil); err != nil {log.Printf("Failed to push: %v", err)}}c.HTML(200, "https", gin.H{"status": "success",})})// 监听并服务于 https://127.0.0.1:8080r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")}
测试
net/http/httptest 包是 HTTP 测试的首选方式。
package mainfunc setupRouter() *gin.Engine {r := gin.Default()r.GET("/ping", func(c *gin.Context) {c.String(200, "pong")})return r}func main() {r := setupRouter()r.Run(":8080")}
测试上面代码的示例:
package mainimport ("net/http""net/http/httptest""testing""github.com/stretchr/testify/assert")func TestPingRoute(t *testing.T) {router := setupRouter()w := httptest.NewRecorder()req, _ := http.NewRequest("GET", "/ping", nil)router.ServeHTTP(w, req)assert.Equal(t, 200, w.Code)assert.Equal(t, "pong", w.Body.String())}
WEBSOKECT
package mainimport ("github.com/gin-gonic/gin""github.com/gorilla/websocket""net/http")var upGrader = websocket.Upgrader{CheckOrigin: func (r *http.Request) bool {return true},}//webSocket请求ping 返回pongfunc ping(c *gin.Context) {//升级get请求为webSocket协议ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)if err != nil {return}defer ws.Close()//读取ws中的数据,一定要,单独write会报错mt, message, err := ws.ReadMessage()if err != nil {return}// 一次read多次sendfor {message = []byte("test")//写入ws数据err = ws.WriteMessage(mt, message)if err != nil {break}time.Sleep(time.Second)}}func main() {bindAddress := "localhost:2303"r := gin.Default()r.GET("/ping", ping)r.Run(bindAddress)}
错误自定义
package mainimport ("github.com/gin-gonic/gin")func MyRecover(c *gin.Context){defer func() {if err:=recover();err!=nil{ //err不等于零值,说明发生了异常c.AbortWithStatusJSON(200,gin.H{"mes":"500"})return}}()c.Next()}func RouteNotFound(c *gin.Context) {c.JSON(200,gin.H{"mes":404})c.Abort()}func MethodNotFound(c *gin.Context) {c.JSON(200,gin.H{"mes":405})c.Abort()}func main() {r := gin.New()r.NoRoute(RouteNotFound) //404r.NoMethod(MethodNotFound)//405r.GET("/ping", MyRecover,func(c *gin.Context) {a:= []string{"1","2","3"}c.String(200,a[3])})r.Run() // 在 0.0.0.0:8080 上监听并服务}
跨域
func Cors() gin.HandlerFunc {return func(c *gin.Context) {c.Header("Access-Control-Allow-Origin", c.GetHeader("Origin")) // 允许的请求源c.Header("Access-Control-Allow-Headers", "Token,SessionId,Content-Type") // 后端可以拿到跨域请求的headerc.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS") // 允许的请求方法c.Header("Access-Control-Allow-Credentials", "true") // 是否允许携带身份凭证// 能够让客户端的js读取到Headerc.Header("Access-Control-Expose-Headers", "X-Powered-By,xxx")// 表明在xxx秒内,不需要再发送预检验请求,可以缓存该结果c.Header("Access-Control-Max-Age", "3600")//如果method是OPTIONS,直接返回成功if c.Request.Method == "OPTIONS" {c.AbortWithStatusJSON(http.StatusOK, "Options Request!")return}// 处理请求c.Next()}}
