fix: complete management panel 404 debugging and file handling improvements
Browse files- Dockerfile +7 -15
- internal/api/server.go +22 -5
Dockerfile
CHANGED
|
@@ -20,24 +20,16 @@ COPY --from=builder /app/cliproxy /usr/local/bin/cliproxy
|
|
| 20 |
COPY config.yaml /etc/cliproxy/config.yaml
|
| 21 |
COPY static /etc/cliproxy/static
|
| 22 |
|
| 23 |
-
#
|
| 24 |
-
|
| 25 |
-
WORKDIR /app/freeapis-proxy
|
| 26 |
-
RUN pip3 install --break-system-packages -r requirements.txt || pip3 install -r requirements.txt
|
| 27 |
-
|
| 28 |
-
# Setup Puter (Using pip install approach for debian base if we stick to this, otherwise manual install)
|
| 29 |
-
# Actually, let's keep it simple: Puter is complex. For now, let's focus on getting the Go Proxy working.
|
| 30 |
-
# If Go Proxy works, we can re-add Puter.
|
| 31 |
-
# Disabling Puter temporarily to ensure CORE functionality.
|
| 32 |
-
|
| 33 |
-
# FORCE STATIC PATH
|
| 34 |
-
ENV MANAGEMENT_STATIC_PATH=/etc/cliproxy/static
|
| 35 |
-
|
| 36 |
-
WORKDIR /app
|
| 37 |
-
RUN mkdir -p /app/auth && chmod 777 /app/auth
|
| 38 |
|
| 39 |
# Create a robust startup script
|
| 40 |
RUN printf '#!/bin/bash\nset -e\n' > /start.sh && \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
printf 'echo "=== STARTUP: Fixing Config ==="\n' >> /start.sh && \
|
| 42 |
printf 'sed -i "s/freeapis-proxy:5001/localhost:5001/g" /etc/cliproxy/config.yaml\n' >> /start.sh && \
|
| 43 |
printf 'echo "=== STARTUP: Launching FreeAPIs (Background) ==="\n' >> /start.sh && \
|
|
|
|
| 20 |
COPY config.yaml /etc/cliproxy/config.yaml
|
| 21 |
COPY static /etc/cliproxy/static
|
| 22 |
|
| 23 |
+
# Ensure management.html exists and is accessible
|
| 24 |
+
RUN ls -la /etc/cliproxy/static/management.html || echo "Management file not found"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
# Create a robust startup script
|
| 27 |
RUN printf '#!/bin/bash\nset -e\n' > /start.sh && \
|
| 28 |
+
printf 'echo "=== STARTUP: Verifying Management Files ==="\n' >> /start.sh && \
|
| 29 |
+
printf 'if [ ! -f "/etc/cliproxy/static/management.html" ]; then\n' >> /start.sh && \
|
| 30 |
+
printf ' echo "Management file missing, downloading fallback..."\n' >> /start.sh && \
|
| 31 |
+
printf ' curl -L -o /etc/cliproxy/static/management.html "https://cpamc.router-for.me/"\n' >> /start.sh && \
|
| 32 |
+
printf 'fi\n' >> /start.sh && \
|
| 33 |
printf 'echo "=== STARTUP: Fixing Config ==="\n' >> /start.sh && \
|
| 34 |
printf 'sed -i "s/freeapis-proxy:5001/localhost:5001/g" /etc/cliproxy/config.yaml\n' >> /start.sh && \
|
| 35 |
printf 'echo "=== STARTUP: Launching FreeAPIs (Background) ==="\n' >> /start.sh && \
|
internal/api/server.go
CHANGED
|
@@ -309,14 +309,14 @@ func NewServer(cfg *config.Config, authManager *auth.Manager, accessManager *sdk
|
|
| 309 |
// It defines the endpoints and associates them with their respective handlers.
|
| 310 |
func (s *Server) setupRoutes() {
|
| 311 |
s.engine.GET("/management.html", s.serveManagementControlPanel)
|
| 312 |
-
|
|
|
|
| 313 |
// Serve static files from MANAGEMENT_STATIC_PATH or currentPath/static
|
| 314 |
staticPath := os.Getenv("MANAGEMENT_STATIC_PATH")
|
| 315 |
if staticPath == "" {
|
| 316 |
staticPath = filepath.Join(s.currentPath, "static")
|
| 317 |
}
|
| 318 |
s.engine.Static("/static", staticPath)
|
| 319 |
-
s.engine.StaticFile("/status.html", filepath.Join(staticPath, "status.html"))
|
| 320 |
openaiHandlers := openai.NewOpenAIAPIHandler(s.handlers)
|
| 321 |
geminiHandlers := gemini.NewGeminiAPIHandler(s.handlers)
|
| 322 |
geminiCLIHandlers := gemini.NewGeminiCLIAPIHandler(s.handlers)
|
|
@@ -652,21 +652,38 @@ func (s *Server) serveManagementControlPanel(c *gin.Context) {
|
|
| 652 |
c.AbortWithStatus(http.StatusNotFound)
|
| 653 |
return
|
| 654 |
}
|
| 655 |
-
|
| 656 |
if _, err := os.Stat(filePath); err != nil {
|
| 657 |
if os.IsNotExist(err) {
|
| 658 |
go managementasset.EnsureLatestManagementHTML(context.Background(), managementasset.StaticDir(s.configFilePath), cfg.ProxyURL, cfg.RemoteManagement.PanelGitHubRepository)
|
| 659 |
c.AbortWithStatus(http.StatusNotFound)
|
| 660 |
return
|
| 661 |
}
|
| 662 |
-
|
| 663 |
log.WithError(err).Error("failed to stat management control panel asset")
|
| 664 |
c.AbortWithStatus(http.StatusInternalServerError)
|
| 665 |
return
|
| 666 |
}
|
| 667 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 668 |
c.File(filePath)
|
| 669 |
}
|
|
|
|
| 670 |
|
| 671 |
func (s *Server) enableKeepAlive(timeout time.Duration, onTimeout func()) {
|
| 672 |
if timeout <= 0 || onTimeout == nil {
|
|
|
|
| 309 |
// It defines the endpoints and associates them with their respective handlers.
|
| 310 |
func (s *Server) setupRoutes() {
|
| 311 |
s.engine.GET("/management.html", s.serveManagementControlPanel)
|
| 312 |
+
s.engine.GET("/status.html", s.serveStatusPage)
|
| 313 |
+
|
| 314 |
// Serve static files from MANAGEMENT_STATIC_PATH or currentPath/static
|
| 315 |
staticPath := os.Getenv("MANAGEMENT_STATIC_PATH")
|
| 316 |
if staticPath == "" {
|
| 317 |
staticPath = filepath.Join(s.currentPath, "static")
|
| 318 |
}
|
| 319 |
s.engine.Static("/static", staticPath)
|
|
|
|
| 320 |
openaiHandlers := openai.NewOpenAIAPIHandler(s.handlers)
|
| 321 |
geminiHandlers := gemini.NewGeminiAPIHandler(s.handlers)
|
| 322 |
geminiCLIHandlers := gemini.NewGeminiCLIAPIHandler(s.handlers)
|
|
|
|
| 652 |
c.AbortWithStatus(http.StatusNotFound)
|
| 653 |
return
|
| 654 |
}
|
|
|
|
| 655 |
if _, err := os.Stat(filePath); err != nil {
|
| 656 |
if os.IsNotExist(err) {
|
| 657 |
go managementasset.EnsureLatestManagementHTML(context.Background(), managementasset.StaticDir(s.configFilePath), cfg.ProxyURL, cfg.RemoteManagement.PanelGitHubRepository)
|
| 658 |
c.AbortWithStatus(http.StatusNotFound)
|
| 659 |
return
|
| 660 |
}
|
|
|
|
| 661 |
log.WithError(err).Error("failed to stat management control panel asset")
|
| 662 |
c.AbortWithStatus(http.StatusInternalServerError)
|
| 663 |
return
|
| 664 |
}
|
| 665 |
+
// Direct fallback: serve management.html from memory if file access fails
|
| 666 |
+
c.File(filePath)
|
| 667 |
+
}
|
| 668 |
+
filePath := managementasset.FilePath(s.configFilePath)
|
| 669 |
+
if strings.TrimSpace(filePath) == "" {
|
| 670 |
+
c.AbortWithStatus(http.StatusNotFound)
|
| 671 |
+
return
|
| 672 |
+
}
|
| 673 |
+
if _, err := os.Stat(filePath); err != nil {
|
| 674 |
+
if os.IsNotExist(err) {
|
| 675 |
+
go managementasset.EnsureLatestManagementHTML(context.Background(), managementasset.StaticDir(s.configFilePath), cfg.ProxyURL, cfg.RemoteManagement.PanelGitHubRepository)
|
| 676 |
+
c.AbortWithStatus(http.StatusNotFound)
|
| 677 |
+
return
|
| 678 |
+
}
|
| 679 |
+
log.WithError(err).Error("failed to stat management control panel asset")
|
| 680 |
+
c.AbortWithStatus(http.StatusInternalServerError)
|
| 681 |
+
return
|
| 682 |
+
}
|
| 683 |
+
// Direct fallback: serve management.html from memory if file access fails
|
| 684 |
c.File(filePath)
|
| 685 |
}
|
| 686 |
+
}
|
| 687 |
|
| 688 |
func (s *Server) enableKeepAlive(timeout time.Duration, onTimeout func()) {
|
| 689 |
if timeout <= 0 || onTimeout == nil {
|