I'm trying to create a url rewrite reverse proxy in golang by httputil.ReverseProxy
which similar to nginx reverse proxy
location /app {
proxy_pass http://127.0.0.1:8080;
}
It passes all path with prefix /app/includes/subpath
to http://127.0.0.1:8080/includes/subpath
How can I pass recursive url
path (<prefix>/pass/from/subpath/to/other/services/
) to http.HandleFunc
?
r := mux.NewRouter().StrictSlash(false)
r.HandleFunc("/proxy/*", func(w http.ResponseWriter, r *http.Request) {
log.Print(r.URL)
proxy.ServeHTTP(w, r)
})
proxy
is based on original source code from httputil
https://golang.org/src/net/http/httputil/reverseproxy.go#L108
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/gorilla/mux"
)
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
switch {
case aslash && bslash:
return a + b[1:]
case !aslash && !bslash:
return a + "/" + b
}
return a + b
}
func NewURLRewriteReverseProxy(target *url.URL) *httputil.ReverseProxy {
targetQuery := target.RawQuery
director := func(req *http.Request) {
// debug
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = singleJoiningSlash(target.Path, req.URL.Path)
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
log.Println(req.URL, req.URL.Path)
}
return &httputil.ReverseProxy{Director: director}
}
func main() {
r := mux.NewRouter().StrictSlash(false)
origin, _ := url.Parse("http://httpbin.org")
proxy := NewURLRewriteReverseProxy(origin)
// proxy := httputil.NewSingleHostReverseProxy(origin)
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "hello")
})
// How can I write the regex or url path in this handler ?
r.HandleFunc("/proxy/{name}/", func(w http.ResponseWriter, r *http.Request) {
proxy.ServeHTTP(w, r)
})
log.Fatal(http.ListenAndServe(":9001", r))
}