Gin frame - routing configuration and installation

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 vendordirectory.
  • Configuration required depends write Gopkg.tomlfile.
  • Gopkg.lock Temporarily can not control.

The Gopkg.tomlincreased 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, vendorthe 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.xxto.

Recommended Reading

This article Welcome forwarding, please indicate the source and author, thank you!

Guess you like

Origin www.cnblogs.com/xinliangcoder/p/11200332.html