package dynamicproxy import ( "log" "net/http" "net/url" "strconv" "sync" "imuslab.com/arozos/mod/network/reverseproxy" ) /* Allow users to setup manual proxying for specific path */ type Router struct { ListenPort int ProxyEndpoints *sync.Map root *ProxyEndpoint mux http.Handler useTLS bool } type RouterOption struct { Port int } type ProxyEndpoint struct { Root string Domain string RequireTLS bool Proxy *reverseproxy.ReverseProxy } type ProxyHandler struct { Parent *Router } func NewDynamicProxy(port int) (*Router, error) { newSyncMap := sync.Map{} thisRouter := Router{ ListenPort: port, ProxyEndpoints: &newSyncMap, useTLS: false, } thisRouter.mux = &ProxyHandler{ Parent: &thisRouter, } return &thisRouter, nil } //Start the dynamic routing func (router *Router) StartProxyService() { go func() { err := http.ListenAndServe(":"+strconv.Itoa(router.ListenPort), router.mux) log.Println("[DynamicProxy] " + err.Error()) }() } /* Add an URL into a custom proxy services */ func (router *Router) AddProxyService(rootname string, domain string, requireTLS bool) error { if domain[len(domain)-1:] == "/" { domain = domain[:len(domain)-1] } webProxyEndpoint := domain if requireTLS { webProxyEndpoint = "https://" + webProxyEndpoint } else { webProxyEndpoint = "http://" + webProxyEndpoint } //Create a new proxy agent for this root path, err := url.Parse(webProxyEndpoint) if err != nil { return err } proxy := reverseproxy.NewReverseProxy(path) router.ProxyEndpoints.Store(rootname, &ProxyEndpoint{ Root: rootname, Domain: domain, RequireTLS: requireTLS, Proxy: proxy, }) return nil } /* Add an default router for the proxy server */ func (router *Router) SetRootProxy(proxyLocation string, requireTLS bool) error { if proxyLocation[len(proxyLocation)-1:] == "/" { proxyLocation = proxyLocation[:len(proxyLocation)-1] } webProxyEndpoint := proxyLocation if requireTLS { webProxyEndpoint = "https://" + webProxyEndpoint } else { webProxyEndpoint = "http://" + webProxyEndpoint } //Create a new proxy agent for this root path, err := url.Parse(webProxyEndpoint) if err != nil { return err } proxy := reverseproxy.NewReverseProxy(path) rootEndpoint := ProxyEndpoint{ Root: "/", Domain: proxyLocation, RequireTLS: requireTLS, Proxy: proxy, } router.root = &rootEndpoint return nil } //Do all the main routing in here func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { targetProxyEndpoint := h.Parent.getTargetProxyEndpointFromRequestURI(r.RequestURI) log.Println(targetProxyEndpoint) if targetProxyEndpoint != nil { h.proxyRequest(w, r, targetProxyEndpoint) } else { h.proxyRequest(w, r, h.Parent.root) } }