client/web: add web client Server struct

Updates tailscale/corp#13775

Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
pull/8838/head
Sonia Appasamy 1 year ago committed by Sonia Appasamy
parent 7815fbe17a
commit 2bc98abbd9

@ -44,7 +44,25 @@ var authenticationRedirectHTML string
var tmpl *template.Template var tmpl *template.Template
var localClient tailscale.LocalClient // Server is the backend server for a Tailscale web client.
type Server struct {
devMode bool
lc *tailscale.LocalClient
}
// NewServer constructs a new Tailscale web client server.
//
// lc is an optional parameter. When not filled, NewServer
// initializes its own tailscale.LocalClient.
func NewServer(devMode bool, lc *tailscale.LocalClient) *Server {
if lc == nil {
lc = &tailscale.LocalClient{}
}
return &Server{
devMode: devMode,
lc: lc,
}
}
func init() { func init() {
tmpl = template.Must(template.New("web.html").Parse(webHTML)) tmpl = template.Must(template.New("web.html").Parse(webHTML))
@ -264,8 +282,8 @@ req.send(null);
</body></html> </body></html>
` `
// Handle processes all requests for the Tailscale web client. // ServeHTTP processes all requests for the Tailscale web client.
func Handle(w http.ResponseWriter, r *http.Request) { func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() ctx := r.Context()
if authRedirect(w, r) { if authRedirect(w, r) {
return return
@ -281,12 +299,12 @@ func Handle(w http.ResponseWriter, r *http.Request) {
return return
} }
st, err := localClient.StatusWithoutPeers(ctx) st, err := s.lc.StatusWithoutPeers(ctx)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
prefs, err := localClient.GetPrefs(ctx) prefs, err := s.lc.GetPrefs(ctx)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
@ -316,7 +334,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
mp.Prefs.AdvertiseRoutes = routes mp.Prefs.AdvertiseRoutes = routes
log.Printf("Doing edit: %v", mp.Pretty()) log.Printf("Doing edit: %v", mp.Pretty())
if _, err := localClient.EditPrefs(ctx, mp); err != nil { if _, err := s.lc.EditPrefs(ctx, mp); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(mi{"error": err.Error()}) json.NewEncoder(w).Encode(mi{"error": err.Error()})
return return
@ -331,7 +349,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
logout = true logout = true
} }
log.Printf("tailscaleUp(reauth=%v, logout=%v) ...", reauth, logout) log.Printf("tailscaleUp(reauth=%v, logout=%v) ...", reauth, logout)
url, err := tailscaleUp(r.Context(), st, postData) url, err := s.tailscaleUp(r.Context(), st, postData)
log.Printf("tailscaleUp = (URL %v, %v)", url != "", err) log.Printf("tailscaleUp = (URL %v, %v)", url != "", err)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
@ -386,9 +404,9 @@ func Handle(w http.ResponseWriter, r *http.Request) {
w.Write(buf.Bytes()) w.Write(buf.Bytes())
} }
func tailscaleUp(ctx context.Context, st *ipnstate.Status, postData postedData) (authURL string, retErr error) { func (s *Server) tailscaleUp(ctx context.Context, st *ipnstate.Status, postData postedData) (authURL string, retErr error) {
if postData.ForceLogout { if postData.ForceLogout {
if err := localClient.Logout(ctx); err != nil { if err := s.lc.Logout(ctx); err != nil {
return "", fmt.Errorf("Logout error: %w", err) return "", fmt.Errorf("Logout error: %w", err)
} }
return "", nil return "", nil
@ -415,7 +433,7 @@ func tailscaleUp(ctx context.Context, st *ipnstate.Status, postData postedData)
watchCtx, cancelWatch := context.WithCancel(ctx) watchCtx, cancelWatch := context.WithCancel(ctx)
defer cancelWatch() defer cancelWatch()
watcher, err := localClient.WatchIPNBus(watchCtx, 0) watcher, err := s.lc.WatchIPNBus(watchCtx, 0)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -423,10 +441,10 @@ func tailscaleUp(ctx context.Context, st *ipnstate.Status, postData postedData)
go func() { go func() {
if !isRunning { if !isRunning {
localClient.Start(ctx, ipn.Options{}) s.lc.Start(ctx, ipn.Options{})
} }
if forceReauth { if forceReauth {
localClient.StartLoginInteractive(ctx) s.lc.StartLoginInteractive(ctx)
} }
}() }()

@ -38,6 +38,7 @@ Tailscale, as opposed to a CLI or a native app.
webf := newFlagSet("web") webf := newFlagSet("web")
webf.StringVar(&webArgs.listen, "listen", "localhost:8088", "listen address; use port 0 for automatic") webf.StringVar(&webArgs.listen, "listen", "localhost:8088", "listen address; use port 0 for automatic")
webf.BoolVar(&webArgs.cgi, "cgi", false, "run as CGI script") webf.BoolVar(&webArgs.cgi, "cgi", false, "run as CGI script")
webf.BoolVar(&webArgs.dev, "dev", false, "run web client in developer mode")
return webf return webf
})(), })(),
Exec: runWeb, Exec: runWeb,
@ -46,6 +47,7 @@ Tailscale, as opposed to a CLI or a native app.
var webArgs struct { var webArgs struct {
listen string listen string
cgi bool cgi bool
dev bool
} }
func tlsConfigFromEnvironment() *tls.Config { func tlsConfigFromEnvironment() *tls.Config {
@ -76,10 +78,10 @@ func runWeb(ctx context.Context, args []string) error {
return fmt.Errorf("too many non-flag arguments: %q", args) return fmt.Errorf("too many non-flag arguments: %q", args)
} }
webHandler := http.HandlerFunc(web.Handle) webServer := web.NewServer(webArgs.dev, nil)
if webArgs.cgi { if webArgs.cgi {
if err := cgi.Serve(webHandler); err != nil { if err := cgi.Serve(webServer); err != nil {
log.Printf("tailscale.cgi: %v", err) log.Printf("tailscale.cgi: %v", err)
return err return err
} }
@ -91,14 +93,14 @@ func runWeb(ctx context.Context, args []string) error {
server := &http.Server{ server := &http.Server{
Addr: webArgs.listen, Addr: webArgs.listen,
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
Handler: webHandler, Handler: webServer,
} }
log.Printf("web server running on: https://%s", server.Addr) log.Printf("web server running on: https://%s", server.Addr)
return server.ListenAndServeTLS("", "") return server.ListenAndServeTLS("", "")
} else { } else {
log.Printf("web server running on: %s", urlOfListenAddr(webArgs.listen)) log.Printf("web server running on: %s", urlOfListenAddr(webArgs.listen))
return http.ListenAndServe(webArgs.listen, webHandler) return http.ListenAndServe(webArgs.listen, webServer)
} }
} }

Loading…
Cancel
Save