Skip to content

Instantly share code, notes, and snippets.

@faelp22
Last active July 25, 2024 13:11
Show Gist options
  • Save faelp22/e14d6a869ee3b3c1e554c695290eae2c to your computer and use it in GitHub Desktop.
Save faelp22/e14d6a869ee3b3c1e554c695290eae2c to your computer and use it in GitHub Desktop.
Um simples proxy reverso feito em Go
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