Last active
July 25, 2024 13:11
-
-
Save faelp22/e14d6a869ee3b3c1e554c695290eae2c to your computer and use it in GitHub Desktop.
Um simples proxy reverso feito em Go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"encoding/json" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"net/http" | |
"net/http/httputil" | |
"net/url" | |
"os" | |
"strings" | |
) | |
type Mservice struct { | |
Hash string `json:"hash"` | |
Path string `json:"path"` | |
Name string `json:"name"` | |
Count int32 `json:"count"` | |
} | |
func (e Mservice) toString() string { | |
return toJson(e) | |
} | |
func toJson(p interface{}) string { | |
bytes, err := json.Marshal(p) | |
if err != nil { | |
fmt.Println(err.Error()) | |
os.Exit(1) | |
} | |
return string(bytes) | |
} | |
// Get env var or default | |
func getEnv(key, fallback string) string { | |
if value, ok := os.LookupEnv(key); ok { | |
return value | |
} | |
return fallback | |
} | |
/* | |
Getters | |
*/ | |
// Get the port to listen on | |
func getListenAddress() string { | |
port := getEnv("PORT", "8000") | |
return "0.0.0.0:" + port | |
} | |
func searchMservice(name string, listaMs []Mservice) Mservice { | |
fmt.Println("searchMservice name=", name) | |
var mservice Mservice | |
for _, elem := range listaMs { | |
if name == elem.Name { | |
mservice = elem | |
break | |
} | |
} | |
return mservice | |
} | |
// Get the port to listen on | |
func getMservice(req *http.Request, listaMs []Mservice) Mservice { | |
prefix := strings.Split(req.RequestURI, "/") | |
fmt.Println("prefix", prefix) | |
return searchMservice(prefix[1], listaMs) | |
} | |
/* | |
Reverse Proxy Logic | |
*/ | |
// Serve a reverse proxy for a given url | |
func serveReverseProxy(target string, res http.ResponseWriter, req *http.Request) { | |
// parse the url | |
url, _ := url.Parse(target) | |
// create the reverse proxy | |
proxy := httputil.NewSingleHostReverseProxy(url) | |
// Update the headers to allow for SSL redirection | |
req.URL.Host = url.Host | |
req.URL.Scheme = url.Scheme | |
req.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 hood | |
proxy.ServeHTTP(res, req) | |
} | |
// Given a request send it to the appropriate url | |
func handleRequestAndRedirect(res http.ResponseWriter, req *http.Request) { | |
// requestPayload := parseRequestBody(req) | |
// url := getProxyUrl(requestPayload.ProxyCondition) | |
var item Mservice = getMservice(req, listaMs) | |
url := item.Path | |
api := strings.Replace(req.RequestURI, "/"+item.Name, "", 1) | |
req.URL.Path = api | |
item.Count++ | |
serveReverseProxy(url, res, req) | |
} | |
func handleRegisterMService(res http.ResponseWriter, req *http.Request) { | |
var tmp Mservice | |
// Read body | |
b, err := ioutil.ReadAll(req.Body) | |
defer req.Body.Close() | |
if err != nil { | |
http.Error(res, err.Error(), 500) | |
return | |
} | |
// Unmarshal | |
err = json.Unmarshal(b, &tmp) | |
if err != nil { | |
http.Error(res, err.Error(), 500) | |
return | |
} | |
var novoRegistro Mservice = Mservice{ | |
Hash: tmp.Hash, | |
Path: "http://" + req.RemoteAddr, //req.Host, | |
Name: tmp.Name, | |
Count: 0, | |
} | |
listaMs = append(listaMs, novoRegistro) | |
res.Write([]byte(listaMs[5].toString())) | |
} | |
var listaMs []Mservice | |
func main() { | |
settings := os.Getenv("SETTINGS") | |
file, _ := ioutil.ReadFile(settings) | |
_ = json.Unmarshal([]byte(file), &listaMs) | |
// start server | |
http.HandleFunc("/register", handleRegisterMService) | |
http.HandleFunc("/", handleRequestAndRedirect) | |
if err := http.ListenAndServe(getListenAddress(), nil); err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment