@@ -44,7 +44,25 @@ var authenticationRedirectHTML string
44
44
45
45
var tmpl * template.Template
46
46
47
- var localClient tailscale.LocalClient
47
+ // Server is the backend server for a Tailscale web client.
48
+ type Server struct {
49
+ devMode bool
50
+ lc * tailscale.LocalClient
51
+ }
52
+
53
+ // NewServer constructs a new Tailscale web client server.
54
+ //
55
+ // lc is an optional parameter. When not filled, NewServer
56
+ // initializes its own tailscale.LocalClient.
57
+ func NewServer (devMode bool , lc * tailscale.LocalClient ) * Server {
58
+ if lc == nil {
59
+ lc = & tailscale.LocalClient {}
60
+ }
61
+ return & Server {
62
+ devMode : devMode ,
63
+ lc : lc ,
64
+ }
65
+ }
48
66
49
67
func init () {
50
68
tmpl = template .Must (template .New ("web.html" ).Parse (webHTML ))
@@ -264,8 +282,8 @@ req.send(null);
264
282
</body></html>
265
283
`
266
284
267
- // Handle processes all requests for the Tailscale web client.
268
- func Handle (w http.ResponseWriter , r * http.Request ) {
285
+ // ServeHTTP processes all requests for the Tailscale web client.
286
+ func ( s * Server ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
269
287
ctx := r .Context ()
270
288
if authRedirect (w , r ) {
271
289
return
@@ -281,12 +299,12 @@ func Handle(w http.ResponseWriter, r *http.Request) {
281
299
return
282
300
}
283
301
284
- st , err := localClient .StatusWithoutPeers (ctx )
302
+ st , err := s . lc .StatusWithoutPeers (ctx )
285
303
if err != nil {
286
304
http .Error (w , err .Error (), http .StatusInternalServerError )
287
305
return
288
306
}
289
- prefs , err := localClient .GetPrefs (ctx )
307
+ prefs , err := s . lc .GetPrefs (ctx )
290
308
if err != nil {
291
309
http .Error (w , err .Error (), http .StatusInternalServerError )
292
310
return
@@ -316,7 +334,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
316
334
mp .Prefs .AdvertiseRoutes = routes
317
335
log .Printf ("Doing edit: %v" , mp .Pretty ())
318
336
319
- if _ , err := localClient .EditPrefs (ctx , mp ); err != nil {
337
+ if _ , err := s . lc .EditPrefs (ctx , mp ); err != nil {
320
338
w .WriteHeader (http .StatusInternalServerError )
321
339
json .NewEncoder (w ).Encode (mi {"error" : err .Error ()})
322
340
return
@@ -331,7 +349,7 @@ func Handle(w http.ResponseWriter, r *http.Request) {
331
349
logout = true
332
350
}
333
351
log .Printf ("tailscaleUp(reauth=%v, logout=%v) ..." , reauth , logout )
334
- url , err := tailscaleUp (r .Context (), st , postData )
352
+ url , err := s . tailscaleUp (r .Context (), st , postData )
335
353
log .Printf ("tailscaleUp = (URL %v, %v)" , url != "" , err )
336
354
if err != nil {
337
355
w .WriteHeader (http .StatusInternalServerError )
@@ -386,9 +404,9 @@ func Handle(w http.ResponseWriter, r *http.Request) {
386
404
w .Write (buf .Bytes ())
387
405
}
388
406
389
- func tailscaleUp (ctx context.Context , st * ipnstate.Status , postData postedData ) (authURL string , retErr error ) {
407
+ func ( s * Server ) tailscaleUp (ctx context.Context , st * ipnstate.Status , postData postedData ) (authURL string , retErr error ) {
390
408
if postData .ForceLogout {
391
- if err := localClient .Logout (ctx ); err != nil {
409
+ if err := s . lc .Logout (ctx ); err != nil {
392
410
return "" , fmt .Errorf ("Logout error: %w" , err )
393
411
}
394
412
return "" , nil
@@ -415,18 +433,18 @@ func tailscaleUp(ctx context.Context, st *ipnstate.Status, postData postedData)
415
433
416
434
watchCtx , cancelWatch := context .WithCancel (ctx )
417
435
defer cancelWatch ()
418
- watcher , err := localClient .WatchIPNBus (watchCtx , 0 )
436
+ watcher , err := s . lc .WatchIPNBus (watchCtx , 0 )
419
437
if err != nil {
420
438
return "" , err
421
439
}
422
440
defer watcher .Close ()
423
441
424
442
go func () {
425
443
if ! isRunning {
426
- localClient .Start (ctx , ipn.Options {})
444
+ s . lc .Start (ctx , ipn.Options {})
427
445
}
428
446
if forceReauth {
429
- localClient .StartLoginInteractive (ctx )
447
+ s . lc .StartLoginInteractive (ctx )
430
448
}
431
449
}()
432
450
0 commit comments