Gin 框架学习:XML/JSON/YAML/ProtoBuf 渲染

xml_json_yaml_protobuf.go:

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/testdata/protoexample"
	"net/http"
)

func main() {
	r := gin.Default()

	// gin.H 是 map[string]interface{} 的一种快捷方式
	r.GET("/someJSON", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/moreJSON", func(c *gin.Context) {
		// 你也可以使用一个结构体
		var msg struct {
			Name    string `json:"user"`
			Message string
			Number  int
		}
		msg.Name = "Lena"
		msg.Message = "hey"
		msg.Number = 123
		// 注意 msg.Name 在 JSON 中变成了 "user"
		// 将输出:{"user":"Lena","Message":"hey","Number":123}
		c.JSON(http.StatusOK, msg)
	})

	r.GET("/someXML", func(c *gin.Context) {
		c.XML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/someYAML", func(c *gin.Context) {
		c.YAML(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
	})

	r.GET("/someProtoBuf", func(c *gin.Context) {
		reps := []int64{int64(1), int64(2)}
		label := "test"
		// protobuf 的具体定义写在 testdata/protoexample 文件中。
		data := &protoexample.Test{
			Label: &label,
			Reps:  reps,
		}
		// 请注意,数据在响应中变为二进制数据
		// 将输出被 protoexample.Test protobuf 序列化了的数据
		c.ProtoBuf(http.StatusOK, data)
	})

	// 监听并在 0.0.0.0:8080 上启动服务
	r.Run(":8080")
}

 

分类至 GO
0条评论

Gin 框架学习:SecureJSON

使用 SecureJSON 防止 json 劫持。如果给定的结构是数组值,则默认预置 while(1); 到响应体。

secruejson.go:

package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()

	r.GET("/someJSON", func(c *gin.Context) {
		names := []string{"lena", "austin", "foo"}

		c.SecureJSON(200, names)
	})

	r.Run(":8080")
}

相关阅读:Why does Google prepend while(1); to their JSON responses?

分类至 GO
0条评论

Gin 框架学习:Query 和 post form

同时接收 post 参数和 query 参数。

query_post.go:

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()

	router.POST("/post", func(c *gin.Context) {
		id := c.Query("id")
		page := c.DefaultQuery("page", "0")
		name := c.PostForm("name")
		message := c.PostForm("message")

		c.String(http.StatusOK, fmt.Sprintf("id: %s; page %s; name: %s; message: %s", id, page, name, message))
	})

	router.Run(":8080")
}

测试:

$ curl -d "name=manu&message=this_is_great" "http://localhost:8080/post?id=1234&page=1"

输出:

id: 1234; page 1; name: manu; message: this_is_great

 

分类至 GO
0条评论

Gin 框架学习:PureJSON

通常,JSON 使用 unicode 替换特殊 HTML 字符,例如 < 变为 \ u003c。如果要按字面对这些字符进行编码,则可以使用 PureJSON。Go 1.6 及更低版本无法使用此功能。

purejson.go:

package main

import "github.com/gin-gonic/gin"

func main() {
	router := gin.Default()

	// 提供 unicode 实体
	router.GET("/json", func(c *gin.Context) {
		// 输出:{"html":"\u003cb\u003eHello, world!\u003c/b\u003e"}
		c.JSON(200, gin.H{
			"html": "<b>Hello, world!</b>",
		})
	})

	// 提供字面字符
	router.GET("/purejson", func(c *gin.Context) {
		// 输出:{"html":"<b>Hello, world!</b>"}
		c.PureJSON(200, gin.H{
			"html": "<b>Hello, world!</b>",
		})
	})

	router.Run(":8080")
}

 

分类至 GO
0条评论

Gin 框架学习:Multipart/Urlencoded 表单

multipart2.go:

package main

import (
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router.POST("/form_post", func(c *gin.Context) {
		message := c.PostForm("message")
		nick := c.DefaultPostForm("nick", "anonymous")

		c.JSON(200, gin.H{
			"status":  "posted",
			"message": message,
			"nick":    nick,
		})
	})
	router.Run(":8080")
}

使用 c.PostForm 方法可以直接获取表单字段,而不必事先声明结构体。如果不存在这个字段,则返回空字符串。

使用 c.DefaultPostForm 方法获取表单字段时,如果字段不存在,将返回给定的默认值。这里要注意,只有表单不包括这个字段时才会返回默认值;如果字段为空字符串,返回的就是空字符串而不是默认值。

分类至 GO
0条评论

Gin 框架学习:Multipart/Urlencoded 绑定

multipart1.go:

package main

import "github.com/gin-gonic/gin"

type LoginForm struct {
	User     string `form:"user" binding:"required"`
	Password string `form:"password" binding:"required"`
}

func main() {
	router := gin.Default()
	router.POST("/login", func(c *gin.Context) {
		// 你可以使用显式绑定声明绑定 multipart form:
		// c.ShouldBindWith(&form, binding.Form)
		// 或者简单地使用 ShouldBind 方法自动绑定:
		var form LoginForm
		// 在这种情况下,将自动选择合适的绑定
		if c.ShouldBind(&form) == nil {
			if form.User == "user" && form.Password == "password" {
				c.JSON(200, gin.H{"status": "you are logged in"})
			} else {
				c.JSON(401, gin.H{"status": "unauthorized"})
			}
		}
	})
	router.Run(":8080")
}

 

分类至 GO
0条评论

Gin 框架学习:JSONP

使用 JSONP 向不同域的服务器请求数据。如果查询参数存在回调,则将回调添加到响应体中。

jsonp.go:

package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()

	r.GET("/JSONP", func(c *gin.Context) {
		data := map[string]interface{}{
			"foo": "bar",
		}

		c.JSONP(200, data)
	})

	r.Run(":8080")
}

运行后访问 http://127.0.0.1:8080/JSONP?callback=myfunc

输出如下:

myfunc({"foo":"bar"});

 

分类至 GO
0条评论

Gin 框架学习:HTTP2 server 推送

http.Pusher 仅支持 go1.8+。

http2.go:

func main() {
	r := gin.Default()
	r.Static("/assets", "./assets") //静态资源目录绑定

	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:8080 上启动服务
	r.RunTLS(":8080", "./testdata/cert.pem", "./testdata/key.pem")
}

assets/app.js:

console.log("hello app.js");

证书文件 cert.pem、key.pem 可以去 Gin 框架目录下的 testdata/certificate 复制过来用。

运行后,要使用 https 访问链接 https://127.0.0.1:8080/

Chrome 浏览器提示证书无效,我们选择继续访问。

按 F12 打开开发者工具,刷新页面,可以看到 app.js 是通过 Push 方式推送到浏览器的。

 

分类至 GO
0条评论

Gin 框架学习:AsciiJSON

使用 AsciiJSON 生成具有转义的非 ASCII 字符的 ASCII-only JSON。 

asciijson.go 代码:

package main

import "net/http"
import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()

	r.GET("/someJSON", func(c *gin.Context) {
		data := map[string]interface{}{
			"lang": "GO语言",
			"tag":  "<br>",
		}
		c.AsciiJSON(http.StatusOK, data)
	})

	r.Run(":8080")
}

执行 go run asciijson.go 后访问 http://127.0.0.1:8080/someJSON,输出:

{"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"}

 

分类至 GO
0条评论