mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-08 17:24:57 +00:00
client/web: add web client Server struct
Updates tailscale/corp#13775 Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
This commit is contained in:
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…
x
Reference in New Issue
Block a user