I want to serve two or more web applications running in a VM (different ports and some time in different directory under the same port) from the host machine and because I need the user to be logged before he can access those apps I can not use a static proxy like Nginx or Apache.
So here is my situation :
192.168.1.1 : is the host ip
192.168.1.2 : is the VM ip
Inside the VM I have this :
192.168.1.2/owncloud : owncloud address
192.168.1.2:8080 : an other app
192.168.1.2:8888 : 3rd app
I want to have this :
192.168.1.1/app1 --> 192.168.1.2/owncloud
192.168.1.1/app2 --> 192.168.1.2:8080
192.168.1.1/app2 --> 192.168.1.2:8888
I have tried to use golang httputil.ReverseProxy to achieve this routing but with no much success: my code is based on this work : gist
package main
import(
"log"
"net/url"
"net/http"
"net/http/httputil"
)
func main() {
remote, err := url.Parse("http://192.168.1.2:8080")
if err != nil {
panic(err)
}
proxy := httputil.NewSingleHostReverseProxy(remote)
http.HandleFunc("/app2", handler(proxy))
err = http.ListenAndServe(":80", nil)
if err != nil {
panic(err)
}
}
func handler(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
log.Println(r.URL)
r.URL.Path = "/"
p.ServeHTTP(w, r)
}
}
Edit :
I have changed the vm ip address: 192.168.1.2 not 192.168.1.1
Make a map like this
hostTarget = map[string]string{
"app1.domain.com": "http://192.168.1.2/owncloud",
"app2.domain.com": "http://192.168.1.2:8080",
"app3.domain.com": "http://192.168.1.2:8888",
}
Use httputil.ReverseProxy
build your handler
type baseHandle struct{}
func (h *baseHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
host := r.Host
if target, ok := hostTarget[host]; ok {
remoteUrl, err := url.Parse(target)
if err != nil {
log.Println("target parse fail:", err)
return
}
proxy := httputil.NewSingleHostReverseProxy(remoteUrl)
proxy.ServeHTTP(w, r)
return
}
w.Write([]byte("403: Host forbidden " + host))
}
ListenAndServe
h := &baseHandle{}
http.Handle("/", h)
server := &http.Server{
Addr: ":8080",
Handler: h,
}
log.Fatal(server.ListenAndServe())
You can cached httputil.ReverseProxy
in global map, all in file above.
Here is a SSLDocker project seen to match with you best.
You'd be better off doing this by hostname rather than URL. eg
owncloud.domain.com -> IP 192.168.1.2,
app2.domain.com -> IP 192.168.1.3
If you weren't already aware, the hostname is just a HTTP request header (Host: domain.com), so you can have several hostnames per IP (Apache calls this "named virtual hosts").
The benefit of using hostnames rather than URLs is that the web app at the other end isn't aware of the URLs you're prefixing yet needs to honour them, so you can run into problems with the URLs being written by the web app not working against the URLs being expected by the reverse proxy. Where as hostname based proxies should work as most web apps wont rewrite the domain name. (this is a huge generalisation though, some web apps will allow you to add a proxy address - but generally you'll run into less issues with hostnames)
The biggest issue is having to set up sub-domains on your name server. I'm assuming your registra / DNS providers allow you to create subdomains free of charge (most should), but if you're using something like dynamic DNS with this running off your home broadband connection, then you will run into problems and will have to buy your own domain name with the subdomains CNAME'ed to your dynamic DNS address (or use a paid account with your dynamic DNS providers if they offer subdomains).
One last thing, if you're looking into owncloud then you might also want to take a look at Pydio (formally AjaxExplore) as well. They both have different strengths and weaknesses, but in my personal opinion Pydio is a better product.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With