|
|
|
|
@ -12,8 +12,11 @@ import ( |
|
|
|
|
"io" |
|
|
|
|
"net" |
|
|
|
|
"net/http" |
|
|
|
|
"net/http/httputil" |
|
|
|
|
"net/netip" |
|
|
|
|
"net/url" |
|
|
|
|
pathpkg "path" |
|
|
|
|
"strings" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"tailscale.com/ipn" |
|
|
|
|
@ -156,13 +159,52 @@ func (b *LocalBackend) serveWebHandler(w http.ResponseWriter, r *http.Request) { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if v := h.Proxy(); v != "" { |
|
|
|
|
io.WriteString(w, "TODO(bradfitz): proxy") |
|
|
|
|
// TODO(bradfitz): this is a lot of setup per HTTP request. We should
|
|
|
|
|
// build the whole http.Handler with all the muxing and child handlers
|
|
|
|
|
// only on start/config change. But this works for now (2022-11-09).
|
|
|
|
|
u, err := url.Parse(expandProxyArg(v)) |
|
|
|
|
if err != nil { |
|
|
|
|
http.Error(w, "bad proxy config", http.StatusInternalServerError) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
rp := httputil.NewSingleHostReverseProxy(u) |
|
|
|
|
rp.Transport = &http.Transport{ |
|
|
|
|
DialContext: b.dialer.SystemDial, |
|
|
|
|
} |
|
|
|
|
rp.ServeHTTP(w, r) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
http.Error(w, "empty handler", 500) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// expandProxyArg returns a URL from s, where s can be of form:
|
|
|
|
|
//
|
|
|
|
|
// * port number ("8080")
|
|
|
|
|
// * host:port ("localhost:8080")
|
|
|
|
|
// * full URL ("http://localhost:8080", in which case it's returned unchanged)
|
|
|
|
|
func expandProxyArg(s string) string { |
|
|
|
|
if s == "" { |
|
|
|
|
return "" |
|
|
|
|
} |
|
|
|
|
if strings.HasPrefix(s, "http://") || strings.HasPrefix(s, "https://") { |
|
|
|
|
return s |
|
|
|
|
} |
|
|
|
|
if allNumeric(s) { |
|
|
|
|
return "http://127.0.0.1:" + s |
|
|
|
|
} |
|
|
|
|
return "http://" + s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func allNumeric(s string) bool { |
|
|
|
|
for i := 0; i < len(s); i++ { |
|
|
|
|
if s[i] < '0' || s[i] > '9' { |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return s != "" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (b *LocalBackend) webServerConfig(sniName string, port uint16) (c ipn.WebServerConfigView, ok bool) { |
|
|
|
|
key := ipn.HostPort(fmt.Sprintf("%s:%v", sniName, port)) |
|
|
|
|
|
|
|
|
|
|