The browser requests the target address, and then gets the result and sends it to the browser. For Go, implementing forwarding only requires a simple line of code to implement it, as shown below:
(address)
Based on this function, simple packaging is carried out to obtain the routing information that needs to be forwarded from the remote admin management center or can be obtained from the local configuration file to achieve dynamic forwarding. The following functions can be implemented according to the business situation in the future:
Develop interfaces to dynamically add proxy rules and forward them
- Illegal filtering interfaces
- Interface current limit
- Unified logging
- …
The code is as follows:
package main import ( "encoding/json" "flag" "fmt" "/gin-gonic/gin" "io" "io/ioutil" "log" "net/http" "net/http/httputil" "net/url" "os" "strings" ) type Respond struct { Success bool Status string Data []Proxy } type Proxy struct { Remark string //describe Prefix string //Forwarding prefix judgment Upstream string //Backend nginx address or IP address RewritePrefix string //Rewrite} var ( InfoLog * ErrorLog * proxyMap = make(map[string]Proxy) ) var adminUrl = ("adminUrl", "", "adminAddress") var profile = ("profile", "", "environment") var proxyFile = ("proxyFile", "", "测试environment的数据") //Log initializationfunc initLog() { errFile, err := ("", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) infoFile, err := ("", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { ("Login file failed:", err) } InfoLog = ((, infoFile), "Info:", ||) ErrorLog = ((, errFile), "Error:", ||) } func main() { router := () //Create a router () initLog() if *profile != "" { ("Loading remote data: %s", *adminUrl) initProxyList() } else { ("Load local configuration data: %s", *proxyFile) loadProxyListFromFile() } ("/*action", Forward) //All requests will be forwarded by the Forward function (":8000") } func initProxyList() { resp, _ := (*adminUrl) if resp != nil && == 200 { bytes, err := () defer () if err != nil { (" err=", err) return } var respond Respond err = (bytes, &respond) if err != nil { (" err=", err) return } proxyList := for _, proxy := range proxyList { //Add backslash to prevent /proxy/test /proxy/test1 from being forwarded correctly when dynamically matched proxyMap[+"/"] = proxy } } } func Forward(c *) { HostReverseProxy(, ) } func HostReverseProxy(w , r *) { if == "/" { (w, "Request path Error") return } //Get forwarded url from memory var upstream = "" if value, ok := proxyMap[]; ok { //If the forwarding address starts with /, it needs to be removed if (, "/") { upstream += (, "/") } else { upstream += } //If the first position is not the beginning, you need to add it if !(, "/") { upstream += "/" + } else { upstream += } //Remove the beginning = (, , "") } // parse the url remote, err := (upstream) ("RequestURI %s upstream %s remote %s", , upstream, remote) if err != nil { panic(err) } = = ("X-Forwarded-Host", ("Host")) = (remote).ServeHTTP(w, r) } func loadProxyListFromFile() { file, err := (*proxyFile) if err != nil { ("err:", err) } var respond Respond // Create a json decoder decoder := (file) err = (&respond) if err != nil { ("LoadProxyListFromFile failed", ()) } proxyList := for _, proxy := range proxyList { proxyMap[+"/"] = proxy } }
The format of proxy_data.json is as follows:
{ "success":true, "status": "ok", "data": [ { "remark": "Test Environment", "prefix": "/division", "upstream": "/", "rewritePrefix": "/api/division" }, { "remark": "Test Environment 1", "prefix": "/division1", "upstream": "/", "rewritePrefix": "" }, { "remark": "Test Environment 2", "prefix": "/division3", "upstream": "/", "rewritePrefix": "/api/division" } ] }
Start the script
## Load local configuration file datago run proxy_agent.go -proxyFile ./proxy_data.json ## Start to get data from the configuration centergo run proxy_agent.go -profile prod -adminUrl http://localhost:3000/proxy/findAll
This is the article about the sample code of the simple API gateway implemented based on Go language. For more related Go API gateway content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!