Put aside your programming language to admire the best standard library I've ever seen. [This was all the code you actually require ...] (https://raw.githubusercontent.com/studygolang/gctt-images/master/reverse-proxy/1_y3GxXdKfZlqa95bl19Rytg.png) Choosing a programming language for your project is not the same as picking your favorite team. You should choose the right tool for your specific job, starting with pragmatism. In this article I will tell you from when and why I think the Go language is so shiny, specifically its standard library is very solid for basic network programming. More specifically, we're going to write a reverse proxy. > **go has a lot to offer, but it really supports these low-level network plumbing tasks, with no better language. * * What is a reverse proxy? * * There is a great argument for traffic forwarding * *. I get the request to the client, send it to another server, get the response from the server, and then back to the original client. The meaning of the reversal is simply that the agent itself determines when to send traffic to where. [Just Beautiful] (https://raw.githubusercontent.com/studygolang/gctt-images/master/reverse-proxy/0_R_W7P1UV4jQEf1j5.gif) Why is this useful? Because the concept of reverse proxies is so simple that it can be applied to many different scenarios: load balancing, A/B testing, caching, validation, and so on. After reading this article, you will learn: * How to respond to HTTP requests * How to parse the request body * How to forward traffic to another server through a reverse proxy # # Our reverse proxy project let's actually write the project. We need a WEB server capable of providing the following features: 1. Gets to request 2. Read the request body, especially the ' proxy_condition ' field 3. If the proxy domain is ' A ', then forward to URL 14. If the proxy domain is ' B ', it is forwarded to URL 25. If the proxy domain is not above, forward to the default url### readiness * [Go] (https://golang.org) locale. * [Http-server] (https://www.npmjs.com/package/http-server) is used to create a simple service. # # # Environment Configuration The first thing we do is write our configuration information to the ringSo you can use them without having to write dead in our source code. I found the best way to create an '. env ' file containing the required environment variables. Here's what I wrote for a specific project: "' Bashexport port=1330export a_condition_url=" http://localhost:1331 "Export b_condition_url=" http://localhost:1332 "Export default_condition_url=" http://localhost:1333 "" > This is my from [Factor App] (https:// 12factor.net/config) The skills acquired in the project. After you save the '. Env ' file, you can run: ' Bashsource. Env ' can run the directive at any time to load the configuration into the environment variable. # # # Project Foundation Work then we create the ' main.go ' file to do the following: 1. Print the ' PORT ', ' a_condition_url ', ' b_condition_url ' and ' default_condition_url ' variables through the log to the console. 2. Listen for requests on the '/' path: ' gopackage mainimport ("bytes" "Encoding/json" "Io/ioutil" "Log" "Net/http" "Net/http/httputil" net/ URL "" OS "" strings ")//Get env var or defaultfunc GETENV (key, fallback string) string {if value, OK: = OS. Lookupenv (key); OK {return Value}return fallback}//Get the port to listen Onfunc getlistenaddress () string {port: = GETENV ("Port", "1338" Return ":" + port}//Log the env variables required for a reverse Proxyfunc logsetup () {a_condtion_url: = os. Getenv ("A_condition_url") b_condtiOn_url: = os. Getenv ("B_condition_url") Default_condtion_url: = OS. Getenv ("Default_condition_url") log. Printf ("Server would run on:%s\n", getlistenaddress ()) log. Printf ("Redirecting to A URL:%s\n", A_condtion_url) log. Printf ("Redirecting to B URL:%s\n", B_condtion_url) log. Printf ("Redirecting to Default URL:%s\n", Default_condtion_url)}//Given a request for send it to the appropriate Urlfunc Han Dlerequestandredirect (res http. Responsewriter, req *http. Request) {//We'll get to this ...} Func Main () {//Log setup Valueslogsetup ()//Start serverhttp. Handlefunc ("/", Handlerequestandredirect) If err: = http. Listenandserve (Getlistenaddress (), nil); Err! = Nil {panic (err)}} "" Now you can run the code. # # # After parsing the request body with the basic skeleton of the project, we need to add logic to handle the request body portion of the parse request. Update the ' handlerequestandredirect ' function to parse the ' proxy_condition ' field from the request body. "' Gotype requestpayloadstruct struct {proxycondition string ' JSON: ' proxy_condition ' '}//Get a JSON decoder for a given re Quests Bodyfunc Requestbodydecoder (Request *http. Request) *json. Decoder {//Read body to Bufferbody, err: = Ioutil. ReadAll (Request. Body) If err! = Nil {log. Printf ("Error reading Body:%v", err) Panic (err)}//Because go Lang is a pain in the the the the the the body and then any SuSE Quent calls//is unable to read the body again....request. Body = Ioutil. Nopcloser (bytes. Newbuffer (body)) return JSON. Newdecoder (Ioutil. Nopcloser (bytes. Newbuffer (body))}//Parse the Requests Bodyfunc Parserequestbody (Request *http. Request) Requestpayloadstruct {decoder: = Requestbodydecoder (Request) var requestpayload requestpayloadstructerr: = Decoder. Decode (&requestpayload) if err! = Nil {panic (err)}return requestpayload}//Given A request send it to the appropriate U Rlfunc Handlerequestandredirect (res http. Responsewriter, req *http. Request) {requestpayload: = Parserequestbody (req)//... more to Come} "" # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Proxy_condition Y_condition ' is a value that can be used to determine where we want to reverse proxy. Remember the three scenarios we mentioned above: 1. If the ' proxy_condition ' value is ' A ', we send the traffic to ' A_condition_url ' 2. If the ' proxy_condition ' value is ' B ', we send traffic to' B_condition_url ' 3. Other cases send traffic to ' Default_condition_url ' go//Log the Typeform payload and redirect Urlfunc Logrequestpayload ( Requestionpayload requestpayloadstruct, Proxyurl string) {log. Printf ("Proxy_condition:%s, Proxy_url:%s\n", Requestionpayload.proxycondition, Proxyurl)}//Get The URL for a given ProX Y conditionfunc getproxyurl (Proxyconditionraw String) string {proxycondition: = strings. ToUpper (proxyconditionraw) A_condtion_url: = OS. Getenv ("A_condition_url") B_condtion_url: = OS. Getenv ("B_condition_url") Default_condtion_url: = OS. Getenv ("Default_condition_url") if proxycondition = = "A" {return a_condtion_url}if proxycondition = "B" {return b_ Condtion_url}return default_condtion_url}//Given A request send it to the appropriate Urlfunc Handlerequestandredirect (r Es http. Responsewriter, req *http. Request) {requestpayload: = parserequestbody (req) URL: = Getproxyurl (requestpayload.proxycondition) logrequestpayload (requestpayload, URL)//More still to come ...} "# # # Reverse proxy to URL finally we came to the actualReverse proxy section. In so many languages to write a reverse proxy you need to consider a lot of things, write large pieces of code. Or at least introduce a complex external library. However, the standard library of Go makes it so simple to create a reverse proxy that you can't even believe it. Here's the most critical line of code you need: ' Gohttputil. Newsinglehostreverseproxy (URL). Servehttp (res, req) "Note that in the code below we have made a few changes to allow it to fully support SSL redirection (though not required). "' go//Serve a reverse proxy for a given Urlfunc Servereverseproxy (target string, res http. Responsewriter, req *http. Request) {//Parse the Urlurl, _: = URL. Parse (target)//Create the reverse proxyproxy: = Httputil. Newsinglehostreverseproxy (URL)//Update the headers to allow for SSL redirectionreq. Url. Host = URL. Hostreq.URL.Scheme = URL. Schemereq.Header.Set ("X-forwarded-host", req. Header.get ("Host")) req. Host = URL. host//Note that servehttp is non blocking and uses a go routine under the hoodproxy. Servehttp (res, req)}//Given A request send it to the appropriate Urlfunc Handlerequestandredirect (res http. Responsewriter, req *http. Request) {requestpayload: = parserequestbody (req) URL: = Getproxyurl (requestpayload.proxycondition) logrequestpayload (requestpayload, URL) servereverSeproxy (URL, res, req)} ' # # # All started well, now start our reverse agent to let it listen to the ' 1330 ' port. Let the other 3 simple services listen to the ' 1331–1333 ' ports separately (in the respective terminal). 1. ' Source. env && Go install && $GOPATH/bin/reverse-proxy-demo ' 2. ' Http-server-p 1331 ' 3. ' Http-server-p 1332 ' 4. ' Http-server-p 1333 ' after these services are started, we can start sending requests with JSON in another terminal like this: ' ' Bashcurl--request GET \--url http://localhost : 1330/\--header ' Content-type:application/json ' \--data ' {"proxy_condition": "A"} ' > If you're looking for a good HTTP request client, I'm trying to push [Insomnia] (https://insomnia.rest). Then we'll see our reverse proxy forwarding traffic to one of the 3 services we configured under the ' Proxy_condition ' field. [Its ALIVE!!!] (https://raw.githubusercontent.com/studygolang/gctt-images/master/reverse-proxy/1_TcyJh0qtYv2N3UOBVVfd0Q.gif) # # # Summary Go for this to provide a lot, but really support it lies in these low-level network pipeline tasks, no better language. The program we write is simple, high performance, reliable and ready to use in the production environment. I can see that in the future I will often use Go to write simple services. The > code is open Source and you can find it on [Github] (Https://github.com/bechurch/reverse-proxy-demo). >️ on [Twitter] (https://www.twitter.com/bnchrch) I only talk about programming and remote work-related things. If you follow me, you won't regret it.
via:https://hackernoon.com/writing-a-reverse-proxy-in-just-one-line-with-go-c1edfa78c84b
Author: Ben Church Translator: Alfred-zhong proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
373 reads ∙2 likes