Gin Web开发02
这章主要解析examples中的Demo。
favicon
解决网站图标问题
package main
import (
"github.com/gin-gonic/gin"
"github.com/thinkerou/favicon"
)
func main() {
app := gin.Default()
app.Use(favicon.New("./favicon.ico")) // 运行目录下的favicon.ico
app.GET("/ping",func(c *gin.Context) {
c.String(200,"Hello favicon.")
})
app.Run(":8080")
}
这里引入一个新的库(gin插件),内部处理了/favicon.ico
这个URL的返回问题。
basic
模拟了一个DB,然后演示了简单的URL和请求问题。
package main
import (
"github.com/gin-gonic/gin"
)
var DB = make(map[string]string)
func main() {
// Disable Console Color
// gin.DisableConsoleColor()
r := gin.Default()
// Ping test
r.GET("/ping","pong")
})
// Get user value
r.GET("/user/:name",func(c *gin.Context) {
user := c.Params.ByName("name")
value,ok := DB[user]
if ok {
c.JSON(200,gin.H{"user": user,"value": value})
} else {
c.JSON(200,"status": "no value"})
}
})
// Authorized group (uses gin.BasicAuth() middleware)
// Same than:
// authorized := r.Group("/")
// authorized.Use(gin.BasicAuth(gin.Credentials{
// "foo": "bar",
// "manu": "123",
//}))
authorized := r.Group("/",gin.BasicAuth(gin.Accounts{
"foo": "bar",// user:foo password:bar
"manu": "123",// user:manu password:123
}))
authorized.POST("admin",func(c *gin.Context) {
user := c.MustGet(gin.AuthUserKey).(string)
// Parse JSON
var json struct {
Value string `json:"value" binding:"required"`
}
if c.Bind(&json) == nil {
DB[user] = json.Value
c.JSON(200,gin.H{"status": "ok"})
}
})
// Listen and Server in 0.0.0.0:8080
r.Run(":8080")
}
- 模拟DB,进行存取操作
- 响应
/ping
URL,给定json返回 - 响应有参数
/user/:name
URL,并通过c.Params
获取URL参数,JSON返回 - 使用Group功能,对Url进行namespace管理。还可以统一对Url进行BasicAuth权限管理。
- Json数据与Form的绑定,通过
c.Bind
进行自动解析(Content-Type一定要是Json才有效)。
auto-tls
介绍如何使用TLS协议自动处理连接
package main
import (
"log"
"github.com/gin-gonic/autotls"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// Ping handler
r.GET("/ping","pong")
})
// 方法1
// log.Fatal(autotls.Run(r,"example1.com","example2.com"))
// 方法2
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))
}
app-engine
介绍如何在google appengine中使用。略过。
http2
通过数字证书,使用SSL加密。
package main
import (
"html/template"
"log"
"os"
"github.com/gin-gonic/gin"
)
var html = template.Must(template.New("https").Parse(` <html> <head> <title>Https Test</title> </head> <body> <h1 style="color:red;">Welcome,Ginner!</h1> </body> </html> `))
func main() {
logger := log.New(os.Stderr,"", 0)
logger.Println("[WARNING] DON'T USE THE EMBED CERTS FROM THIS EXAMPLE IN PRODUCTION ENVIRONMENT,GENERATE YOUR OWN!")
r := gin.Default()
r.SetHTMLTemplate(html)
r.GET("/welcome",func(c *gin.Context) {
c.HTML(200,"https",gin.H{
"status": "success",})
})
// Listen and Server in https://127.0.0.1:8080
r.RunTLS(":8080","./testdata/server.pem","./testdata/server.key")
}
使用RunTLS后,默认使用HTTPS连接。
graceful-shutdown
说明如何可以优雅地关闭服务。基本思路是使用协程和Chann。一般用不上。
upload-file
single
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.Static("/","./public")
router.POST("/upload",func(c *gin.Context) {
name := c.PostForm("name")
email := c.PostForm("email")
// Source
file,err := c.FormFile("file")
if err != nil {
c.String(http.StatusBadRequest,fmt.Sprintf("get form err: %s",err.Error()))
return
}
if err := c.SaveUploadedFile(file,file.Filename); err != nil {
c.String(http.StatusBadRequest,fmt.Sprintf("upload file err: %s",err.Error()))
return
}
c.String(http.StatusOK,fmt.Sprintf("File %s uploaded successfully with fields name=%s and email=%s.",file.Filename,name,email))
})
router.Run(":8080")
}
multiple
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.Static("/",func(c *gin.Context) {
name := c.PostForm("name")
email := c.PostForm("email")
// Multipart form
form,err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest,err.Error()))
return
}
files := form.File["files"]
for _,file := range files {
if err := c.SaveUploadedFile(file,file.Filename); err != nil {
c.String(http.StatusBadRequest,err.Error()))
return
}
}
c.String(http.StatusOK,fmt.Sprintf("Uploaded successfully %d files with fields name=%s and email=%s.",len(files),email))
})
router.Run(":8080")
}
realtime-chat
package main
import (
"fmt"
"io"
"math/rand"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.SetHTMLTemplate(html)
router.GET("/room/:roomid",roomGET)
router.POST("/room/:roomid",roomPOST)
router.DELETE("/room/:roomid",roomDELETE)
router.GET("/stream/:roomid",stream)
router.Run(":8080")
}
func stream(c *gin.Context) {
roomid := c.Param("roomid")
listener := openListener(roomid)
defer closeListener(roomid,listener)
c.Stream(func(w io.Writer) bool {
c.SSEvent("message",<-listener)
return true
})
}
func roomGET(c *gin.Context) {
roomid := c.Param("roomid")
userid := fmt.Sprint(rand.Int31())
c.HTML(200,"chat_room",gin.H{
"roomid": roomid,"userid": userid,})
}
func roomPOST(c *gin.Context) {
roomid := c.Param("roomid")
userid := c.PostForm("user")
message := c.PostForm("message")
room(roomid).Submit(userid + ": " + message)
c.JSON(200,gin.H{
"status": "success","message": message,})
}
func roomDELETE(c *gin.Context) {
roomid := c.Param("roomid")
deleteBroadcast(roomid)
}
这里只展示main的代码。整个项目思路是:
1. GET /room/:roomid
得到一个发送pub的页面,内部调用POST /room/:roomid
这个url.
2. GET /stream/:roomid
这个建立了Chunck的URL长连接,接收从服务器c.Stream
发送过来的数据,没有数据时,等待,直至超时。
其中,服务器使用了window.EventSource
机制,在服务端使用c.Stream
接口中c.SSEvent
来发送event。
realtime-advanced
在realtime-chat的基础上,添加了状态监控,消息列表等展示性质功能。
静态文件处理
func main() {
router := gin.Default()
router.Static("/assets","./assets")
router.StaticFS("/more_static",http.Dir("my_file_system"))
router.StaticFile("/favicon.ico","./resources/favicon.ico")
// Listen and server on 0.0.0.0:8080
router.Run(":8080")
}
原文链接:https://www.f2er.com/go/187764.html