Realize RestFul interaction based on go language

1. Restful

1.1 Introduction to RestFul

RESTFUL (Representational State Transfer) is a web application design style and development method based on HTTP or HTTPS, which can be defined in XML format or JSON format. RESTFUL is suitable for scenarios where mobile Internet manufacturers serve as business interfaces, and realizes the function of third-party OTT calling mobile network resources. The action types are adding, changing, and deleting the called resources.

REST tends to be designed and implemented in a simpler and lighter way. It is worth noting that REST does not have a clear standard, but more like a design style.

1.2 Principles and Conditions

  1. REST refers to a set of architectural constraints and principles. An application or design that satisfies these constraints and principles is RESTful

  2. The most important REST principle for web applications is that the interaction between client and server is stateless between requests , i.e.: 1) Every request from
    client to server must contain the information necessary to understand the request2
    ) the server restarts at any point of time, the client will not be notified
    3) stateless requests can be answered by any available server

  3. On the server side, application state and functionality can be grouped into various resources

1.3 Features

  1. Each URI represents a resource
  2. The client uses GET, POST, PUT, and DELETE to operate on server resources: GET is used to obtain resources, POST is used to create new resources (it can also be used to update resources), PUT is used to update resources, and DELETE Used to delete resources;
  3. The interaction between the client and the server is stateless between requests, every request from the client to the server must contain the information necessary to understand the request

2. The gin package in go

Gin is a web framework written in Go language. It has fast running speed, grouped routers, good crash capture and error handling, and very good support for middleware and json. In short, in the field of Go language development, it is a Web framework worth studying. The open source URL: https://github.com/gin-gonic/gin

2.1 Download and load the gin package:

go get "https://github.com/gin-gonic/gin"
import "https://github.com/gin-gonic/gin"

2.2 Simple use of gin package based on HTTP

package main
import(
	"fmt"
	"https://github.com/gin-gonic/gin"
)
func main(){
    
    
	router := gin.Default()
	router.GET("/getConfig",func (context *gin.Context){
    
    
		context.JSON(http.StatusOK, gin.H{
    
    
			"code": http.StatusOK,
			"data": "message" 
		})
	})
	router.Run(":8080")
}

2.3 Simple use of gin package based on HTTPS

package main
import(
	"fmt"
	"https://github.com/gin-gonic/gin"
)
func LoadTls(port int) gin.HandlerFunc {
    
    
	return func(c *gin.Context) {
    
    
		middleware := secure.New(secure.Options{
    
    
			SSLRedirect: true,
			SSLHost:  "localhost:" + strconv.Itoa(port),
		})
		err := middleware.Process(c.Writer, c.Request)
		if err != nil {
    
    
			//如果出现错误,请不要继续。
			fmt.Println(err)
			return
		}
		// 继续往下处理
		c.Next()
	}
}
func main(){
    
    
	router := gin.Default()
	router.Use(LoadTls(8000))
	router.GET("/getConfig",func (context *gin.Context){
    
    
		context.JSON(http.StatusOK, gin.H{
    
    
			"code": http.StatusOK,
			"data": "message" 
		})
	})
	router.RunTLS(":8080", "server.crt","server.key")
}

3. Parse the config.json file server

3.1 Set interface and protocol


type ConfigParseServer struct {
    
    
}

func LoadTls(port int) gin.HandlerFunc {
    
    
	return func(c *gin.Context) {
    
    
		middleware := secure.New(secure.Options{
    
    
			SSLRedirect: true,
			SSLHost:     "localhost:" + strconv.Itoa(port),
		})
		err := middleware.Process(c.Writer, c.Request)
		if err != nil {
    
    
			//如果出现错误,请不要继续。
			fmt.Println(err)
			return
		}
		// 继续往下处理
		c.Next()
	}
}

func (*ConfigParseServer) GinHttps(isHttps bool) error {
    
    

	router := gin.Default()

	router.GET("/getConfigs/config", hello.GetAllConfigData)
	router.GET("/getConfig/server", hello.GetServerInfo)
	router.GET("/getConfig/client", hello.GetClientInfo)

	router.POST("/setServerInfo/", hello.SetServerInfo)
	router.POST("/setClientInfo/", hello.SetClientInfo)

	if isHttps {
    
    
		router.Use(LoadTls(8000))
		return router.RunTLS(":8000", "server.crt", "server.key")
	}
	return router.Run(":8080")
}

func main() {
    
    
	var configParseServer ConfigParseServer
	fmt.Printf("请输入0/1来确定是否使用https: ")
	var valve bool
	fmt.Scan(&valve)
	configParseServer.GinHttps(valve)
}

3.2 Implement the interface

func GetJsonData() []byte {
    
    
	data, err := os.ReadFile("./hello/config.json")
	if err != nil {
    
    
		fmt.Println("readfile error")
	}
	return data
}

func ParseJson2Struct() *AutoGenerated {
    
    
	datafig, err := os.ReadFile("./hello/config.json")
	if err != nil {
    
    
		fmt.Println("ParseJson: os.ReadFile.....")
	}
	cfg := new(AutoGenerated)
	err = json.Unmarshal(datafig, cfg)
	if err != nil {
    
    
		fmt.Println("ParseJson: json.Unmarshal.....")
	}
	return cfg
}


func SetConfigInfo(context *gin.Context, modle string) (int, string) {
    
    
	var code int = -1
	var errorMessage string
	raw := GetJsonData()
	var configStruct AutoGenerated
	err := json.Unmarshal(raw, &configStruct)
	if err != nil {
    
    
		fmt.Println("SetConfigInfo: json.Unmarshal failed")
	}
	data, _ := io.ReadAll(context.Request.Body)
	var res map[string]interface{
    
    }
	err = json.Unmarshal(data, &res)
	if err != nil {
    
    
		fmt.Println("GetConfigInfo: json.Unmarshal failed...")
	}

	for k := range res {
    
    
		if k != modle {
    
    
			errorMessage = "Only the config of " + modle + " can be modified here"
			return code, errorMessage
		}
	}

	err = json.Unmarshal(data, &configStruct)
	if err != nil {
    
    
		Logger("Error", "json Unmarshal failed")
		errorMessage = "type of value is wrong"
		return code, errorMessage
	}

	Indata, err := json.MarshalIndent(configStruct, "", "  ")
	if err != nil {
    
    
		fmt.Println("json.MarshalIndent failed")
	}

	fp, err := os.Create("./newConfig.json")
	if err != nil {
    
    
		fmt.Println("os.Create fail...")
	}
	defer fp.Close()

	fp.Write(Indata)

	code = 0
	errorMessage = "modify success!!!"
	return code, errorMessage
}
func SetServerInfo(context *gin.Context) {
    
    
	code, reason := SetConfigInfo(context, "server")
	var newConfig AutoGenerated

	data, err := os.ReadFile("./newConfig.json")
	if err != nil {
    
    
		Logger("Error", "SetServerVersionInfo: ReadFile failed")
	}
	err = json.Unmarshal(data, &newConfig)
	if err != nil {
    
    
		Logger("Error", "SetServerVersionInfo: json Unmarshal failed")
	}

	var param interface{
    
    }

	if reason == "modify success!!!" {
    
    
		param = newConfig.Server
	} else {
    
    
		param = nil
	}

	context.JSON(http.StatusOK, gin.H{
    
    
		"code":   code,
		"reason": reason,
		"params": param,
	})
}

func SetClientInfo(context *gin.Context) {
    
    
	code, reason := SetConfigInfo(context, "client")
	var newConfig AutoGenerated

	data, err := os.ReadFile("./newConfig.json")
	if err != nil {
    
    
		Logger("Error", "SetServerVersionInfo: ReadFile failed")
	}
	err = json.Unmarshal(data, &newConfig)
	if err != nil {
    
    
		Logger("Error", "SetServerVersionInfo: json Unmarshal failed")
	}

	var param interface{
    
    }

	if reason == "modify success!!!" {
    
    
		param = newConfig.Client
	} else {
    
    
		param = nil
	}

	context.JSON(http.StatusOK, gin.H{
    
    
		"code":   code,
		"reason": reason,
		"params": param,
	})
}

func GetConfigStruct() *AutoGenerated {
    
    
	//fmt.Println(*ParseJson2Struct())
	return ParseJson2Struct()
}

func GetServerInfo(context *gin.Context) {
    
    
	context.JSON(http.StatusOK, gin.H{
    
    
		"code": http.StatusOK,
		//"reason": "get data success",
		"data": GetConfigStruct().Server,
	})
}

func GetClientInfo(context *gin.Context) {
    
    
	context.JSON(http.StatusOK, gin.H{
    
    
		"code": http.StatusOK,
		//"reason": "get data success",
		"data": GetConfigStruct().Client,
	})
}

After the server is deployed, it is a headache to nest json information to get the key in the code, write the following code

3.3 json fetch key

func getKeys(data map[string]interface{
    
    }) string {
    
    
	var j int
	var flag int
	var keyList []string
	//fmt.Println(len(data))
	for j = 0; j < 20; j++ {
    
    
		flag = 0
		for k, v := range data {
    
    
			keyList = append(keyList, k)
			switch value := v.(type) {
    
    
			case string, int, float64, uint:
				flag = -1
			case map[string]interface{
    
    }:
				data = value
				fmt.Println(data)
			}
		}
		if flag == -1 {
    
    
			break
		}
	}
	queryString := keyList[0]
	var i int
	if len(keyList) > 1 {
    
    
		queryString += "."
		for i = 1; i < len(keyList)-1; i++ {
    
    
			queryString += keyList[i]
			queryString += "."
		}
		queryString += keyList[i]
	}
	return queryString    //key的格式为key1.key2.key3...
}
//如上取到的key的格式,可以通过jmespath.Search去json中取相应的value
func getOneClassInfo(context *gin.Context, postJsondata []byte) {
    
    
	jsonData := GetJsonData()
	var totalData interface{
    
    }
	err := json.Unmarshal(jsonData, &totalData)
	if err != nil {
    
    
		fmt.Println("getServerInfo:111json.Unmarshal")
	}

	var jsonMap map[string]interface{
    
    }
	err = json.Unmarshal(postJsondata, &jsonMap)
	if err != nil {
    
    
		fmt.Println("getServerInfo:222json.Unmarshal")
	}

	path := getKeys(jsonMap)
	res, err := jmespath.Search(path, totalData)
	if err != nil {
    
    
		fmt.Println("jmespath Search failed....")
	}
	context.JSON(http.StatusOK, res)
}

Guess you like

Origin blog.csdn.net/weixin_54792212/article/details/128973284