(c *gin.Context)
| 867 | } |
| 868 | |
| 869 | func (s *Server) serveManagementControlPanel(c *gin.Context) { |
| 870 | cfg := s.cfg |
| 871 | if cfg == nil || cfg.Home.Enabled || cfg.RemoteManagement.DisableControlPanel { |
| 872 | c.AbortWithStatus(http.StatusNotFound) |
| 873 | return |
| 874 | } |
| 875 | filePath := managementasset.FilePath(s.configFilePath) |
| 876 | if strings.TrimSpace(filePath) == "" { |
| 877 | c.AbortWithStatus(http.StatusNotFound) |
| 878 | return |
| 879 | } |
| 880 | |
| 881 | if _, err := os.Stat(filePath); err != nil { |
| 882 | if os.IsNotExist(err) { |
| 883 | if !managementasset.AutoUpdateEnabled(cfg) { |
| 884 | c.AbortWithStatus(http.StatusNotFound) |
| 885 | return |
| 886 | } |
| 887 | // Synchronously ensure management.html is available with a detached context. |
| 888 | // Control panel bootstrap should not be canceled by client disconnects. |
| 889 | if !managementasset.EnsureLatestManagementHTML(context.Background(), managementasset.StaticDir(s.configFilePath), cfg.ProxyURL, cfg.RemoteManagement.PanelGitHubRepository) { |
| 890 | c.AbortWithStatus(http.StatusNotFound) |
| 891 | return |
| 892 | } |
| 893 | } else { |
| 894 | log.WithError(err).Error("failed to stat management control panel asset") |
| 895 | c.AbortWithStatus(http.StatusInternalServerError) |
| 896 | return |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | c.File(filePath) |
| 901 | } |
| 902 | |
| 903 | func (s *Server) enableKeepAlive(timeout time.Duration, onTimeout func()) { |
| 904 | if timeout <= 0 || onTimeout == nil { |
nothing calls this directly
no test coverage detected