table of Contents
Outline
Look Gin framework of the official description:
Gin is a use Go (Golang) web framework written. It is similar to a martini but API framework has better performance, due httprouter, nearly 40 times faster. If you are the performance and efficiency of suitors, you'll love Gin.
Yes, that is with Gin to write API interface.
Share this article Gin Gin installation and routing configuration.
Feature point comprising the following routing configurations:
- Achieved, packet routing version v1, v2 version.
- It realized, generating a signature verification and validation.
- Achieved, reads the configuration in the configuration file.
Gin installation
You must first install Go, Go installation can refer to: Go - Environment installation .
Mounting frame can refer to the official website:
https://gin-gonic.com/zh-cn/docs/quickstart/
I installed, using a dep installation, to share with you.
dep is what?
It is Golang official dependency management tool, it can be considered similar to PHP in the composer.
This is not much to do in the introduction, you can get to know yourself, installation is relatively simple.
This machine is my Mac, install a single command:
brew install dep
Next, we create a new project: ginDemo.
Executed in ginDemo catalog:
dep init
Is finished, it will generate the following three documents:
├─ ginDemo
│ ├─ vendor
│ ├─ Gopkg.toml
│ ├─ Gopkg.lock
- Dependencies are downloaded to the
vendor
directory. - Configuration required depends write
Gopkg.toml
file. Gopkg.lock
Temporarily can not control.
The Gopkg.toml
increased reliance file:
[[constraint]]
name = "github.com/gin-gonic/gin"
version = "1.4.0"
Add a main.go file:
// 官方 Demo
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
ginDemo directory execute:
dep ensure
Is finished, vendor
the directory exist the installation package, then the entire directory structure as follows:
├─ ginDemo
│ ├─ vendor
│ ├── github.com
│ ├── ...
│ ├── golang.org
│ ├── ...
│ ├── gopkg.in
│ ├── ...
│ ├─ Gopkg.toml
│ ├─ Gopkg.lock
│ ├─ main.go
ginDemo directory execute:
go run main.go
Browser access:http://localhost:8080/ping
We're done!
Routing Configuration
For example, our interface address is this:
/v1/product/add
/v1/member/add
/v2/product/add
/v2/member/add
Assuming that the demand is such that the interface supports a variety of ways request, v1 without signature verification, v2 require signature verification, routing documents should be written:
package router
import (
"ginDemo/common"
"ginDemo/controller/v1"
"ginDemo/controller/v2"
"github.com/gin-gonic/gin"
"net/url"
"strconv"
)
func InitRouter(r *gin.Engine) {
r.GET("/sn", SignDemo)
// v1 版本
GroupV1 := r.Group("/v1")
{
GroupV1.Any("/product/add", v1.AddProduct)
GroupV1.Any("/member/add", v1.AddMember)
}
// v2 版本
GroupV2 := r.Group("/v2", common.VerifySign)
{
GroupV2.Any("/product/add", v2.AddProduct)
GroupV2.Any("/member/add", v2.AddMember)
}
}
func SignDemo(c *gin.Context) {
ts := strconv.FormatInt(common.GetTimeUnix(), 10)
res := map[string]interface{}{}
params := url.Values{
"name" : []string{"a"},
"price" : []string{"10"},
"ts" : []string{ts},
}
res["sn"] = common.CreateSign(params)
res["ts"] = ts
common.RetJson("200", "", res, c)
}
.Any
He expressed support for a variety of requests ways.
controller/v1
V1 represents the version of the file.
controller/v2
V2 represents the version of the file.
SignDemo
Representation to generate the signature Demo.
Next, some code fragments are given:
Signature verification methods:
// 验证签名
func VerifySign(c *gin.Context) {
var method = c.Request.Method
var ts int64
var sn string
var req url.Values
if method == "GET" {
req = c.Request.URL.Query()
sn = c.Query("sn")
ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64)
} else if method == "POST" {
req = c.Request.PostForm
sn = c.PostForm("sn")
ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64)
} else {
RetJson("500", "Illegal requests", "", c)
return
}
exp, _ := strconv.ParseInt(config.API_EXPIRY, 10, 64)
// 验证过期时间
if ts > GetTimeUnix() || GetTimeUnix() - ts >= exp {
RetJson("500", "Ts Error", "", c)
return
}
// 验证签名
if sn == "" || sn != CreateSign(req) {
RetJson("500", "Sn Error", "", c)
return
}
}
Generation method signature:
// 生成签名
func CreateSign(params url.Values) string {
var key []string
var str = ""
for k := range params {
if k != "sn" {
key = append(key, k)
}
}
sort.Strings(key)
for i := 0; i < len(key); i++ {
if i == 0 {
str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i]))
} else {
str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i]))
}
}
// 自定义签名算法
sign := MD5(MD5(str) + MD5(config.APP_NAME + config.APP_SECRET))
return sign
}
Obtaining parameters of the method:
// 获取 Get 参数
name := c.Query("name")
price := c.DefaultQuery("price", "100")
// 获取 Post 参数
name := c.PostForm("name")
price := c.DefaultPostForm("price", "100")
// 获取 Get 所有参数
ReqGet = c.Request.URL.Query()
//获取 Post 所有参数
ReqPost = c.Request.PostForm
v1 business code:
package v1
import "github.com/gin-gonic/gin"
func AddProduct(c *gin.Context) {
// 获取 Get 参数
name := c.Query("name")
price := c.DefaultQuery("price", "100")
c.JSON(200, gin.H{
"v1" : "AddProduct",
"name" : name,
"price" : price,
})
}
v2 business code:
package v2
import (
"github.com/gin-gonic/gin"
)
func AddProduct(c *gin.Context) {
// 获取 Get 参数
name := c.Query("name")
price := c.DefaultQuery("price", "100")
c.JSON(200, gin.H{
"v1" : "AddProduct",
"name" : name,
"price" : price,
})
}
Then, looking directly at the effect of it.
Access v1 Interface:
After the visit, return data directly, do not take the signature verification.
Access v2 interfaces:
Enter this verification:
// 验证过期时间
if ts > GetTimeUnix() || GetTimeUnix() - ts >= exp {
RetJson("500", "Ts Error", "", c)
return
}
Modify the legal time stamp:
Enter this verification:
// 验证签名
if sn == "" || sn != CreateSign(req) {
RetJson("500", "Sn Error", "", c)
return
}
After modification as a legitimate signature:
Thus, a simple routing configuration has been achieved.
Yes, there is a point did not say, is how to read the configuration file configuration, I will do so:
package config
const (
PORT = ":8080"
APP_NAME = "ginDemo"
APP_SECRET = "6YJSuc50uJ18zj45"
API_EXPIRY = "120"
)
Config package introduced directly config.xx
to.
Recommended Reading
- Go - Function
- Go - cycling
- Go - Map collection
- Go - Struct structure
- Go - Slice Slice
- Go - Array
- Go - variable declaration
- Go - Environment Installation
This article Welcome forwarding, please indicate the source and author, thank you!