Gin开发02

来源:互联网 发布:python读txt文件 编辑:程序博客网 时间:2024/06/03 15:17

Gin Web开发02

这章主要解析examples中的Demo。

favicon

解决网站图标问题

package mainimport (    "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 mainimport (    "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", func(c *gin.Context) {        c.String(200, "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, gin.H{"user": user, "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")}
  1. 模拟DB,进行存取操作
  2. 响应/pingURL,给定json返回
  3. 响应有参数/user/:nameURL,并通过c.Params获取URL参数,JSON返回
  4. 使用Group功能,对Url进行namespace管理。还可以统一对Url进行BasicAuth权限管理。
  5. Json数据与Form的绑定,通过c.Bind进行自动解析(Content-Type一定要是Json才有效)。

auto-tls

介绍如何使用TLS协议自动处理连接

package mainimport (    "log"    "github.com/gin-gonic/autotls"    "github.com/gin-gonic/gin")func main() {    r := gin.Default()    // Ping handler    r.GET("/ping", func(c *gin.Context) {        c.String(200, "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 mainimport (    "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 mainimport (    "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 mainimport (    "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")        // Multipart form        form, err := c.MultipartForm()        if err != nil {            c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))            return        }        files := form.File["files"]        for _, file := range files {            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("Uploaded successfully %d files with fields name=%s and email=%s.", len(files), name, email))    })    router.Run(":8080")}

展示如何处理多个文件上次功能。

realtime-chat

package mainimport (    "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")}
原创粉丝点击