refactor(api): remove http routes in favor of webkit message bridge
- commit
- 6ad5700593c6f2ceb7fa32c0fa4d6ea0d1dbc08f
- author
- bamen · · 2025-09-16 08:13 UTC
- parent
- 382faa5
- signature
- unsigned
2 files · +0 -205
D internal/app/api/routes.go +0 -162
| @@ -1,162 +0,0 @@ | |||
| 1 | - | package api | |
| 2 | - | ||
| 3 | - | import ( | |
| 4 | - | "context" | |
| 5 | - | "encoding/json" | |
| 6 | - | "log" | |
| 7 | - | neturl "net/url" | |
| 8 | - | "strconv" | |
| 9 | - | ||
| 10 | - | "github.com/bnema/dumber/internal/app/constants" | |
| 11 | - | "github.com/bnema/dumber/internal/config" | |
| 12 | - | "github.com/bnema/dumber/services" | |
| 13 | - | ) | |
| 14 | - | ||
| 15 | - | // Handler provides API endpoint handling functionality | |
| 16 | - | type Handler struct { | |
| 17 | - | browserService *services.BrowserService | |
| 18 | - | } | |
| 19 | - | ||
| 20 | - | // NewHandler creates a new API handler | |
| 21 | - | func NewHandler(browserService *services.BrowserService) *Handler { | |
| 22 | - | return &Handler{ | |
| 23 | - | browserService: browserService, | |
| 24 | - | } | |
| 25 | - | } | |
| 26 | - | ||
| 27 | - | // HandleRenderingStatus handles GET /rendering/status endpoint | |
| 28 | - | func (h *Handler) HandleRenderingStatus(cfg *config.Config) (string, []byte, bool) { | |
| 29 | - | log.Printf("[api] GET /rendering/status") | |
| 30 | - | // Report configured rendering mode; runtime GPU state depends on WebKit internals | |
| 31 | - | resp := struct { | |
| 32 | - | Mode string `json:"mode"` | |
| 33 | - | }{Mode: string(cfg.RenderingMode)} | |
| 34 | - | b, _ := json.Marshal(resp) | |
| 35 | - | return constants.ContentTypeJSON, b, true | |
| 36 | - | } | |
| 37 | - | ||
| 38 | - | // HandleConfig handles GET /config endpoint | |
| 39 | - | func (h *Handler) HandleConfig(cfg *config.Config) (string, []byte, bool) { | |
| 40 | - | log.Printf("[api] GET /config") | |
| 41 | - | // Build config info | |
| 42 | - | cfgPath, _ := config.GetConfigFile() | |
| 43 | - | info := struct { | |
| 44 | - | ConfigPath string `json:"config_path"` | |
| 45 | - | DatabasePath string `json:"database_path"` | |
| 46 | - | SearchShortcuts map[string]config.SearchShortcut `json:"search_shortcuts"` | |
| 47 | - | Appearance config.AppearanceConfig `json:"appearance"` | |
| 48 | - | }{ | |
| 49 | - | ConfigPath: cfgPath, | |
| 50 | - | DatabasePath: cfg.Database.Path, | |
| 51 | - | SearchShortcuts: cfg.SearchShortcuts, | |
| 52 | - | Appearance: cfg.Appearance, | |
| 53 | - | } | |
| 54 | - | b, _ := json.Marshal(info) | |
| 55 | - | return constants.ContentTypeJSON, b, true | |
| 56 | - | } | |
| 57 | - | ||
| 58 | - | // HandleHistoryRecent handles GET /history/recent endpoint | |
| 59 | - | func (h *Handler) HandleHistoryRecent(u *neturl.URL) (string, []byte, bool) { | |
| 60 | - | log.Printf("[api] GET /history/recent%s", u.RawQuery) | |
| 61 | - | // Parse limit and offset | |
| 62 | - | q := u.Query() | |
| 63 | - | limit := 20 | |
| 64 | - | if l := q.Get("limit"); l != "" { | |
| 65 | - | if n, err := strconv.Atoi(l); err == nil && n > 0 { | |
| 66 | - | limit = n | |
| 67 | - | } | |
| 68 | - | } | |
| 69 | - | offset := 0 | |
| 70 | - | if o := q.Get("offset"); o != "" { | |
| 71 | - | if n, err := strconv.Atoi(o); err == nil && n >= 0 { | |
| 72 | - | offset = n | |
| 73 | - | } | |
| 74 | - | } | |
| 75 | - | ||
| 76 | - | ctx := context.Background() | |
| 77 | - | var entries []interface{} | |
| 78 | - | ||
| 79 | - | // Use paginated version if offset is provided | |
| 80 | - | if offset > 0 || q.Has("offset") { | |
| 81 | - | histEntries, err := h.browserService.GetRecentHistoryWithOffset(ctx, limit, offset) | |
| 82 | - | if err != nil { | |
| 83 | - | return constants.ContentTypeJSON, []byte("[]"), true | |
| 84 | - | } | |
| 85 | - | // Convert to interface slice for JSON marshaling | |
| 86 | - | entries = make([]interface{}, len(histEntries)) | |
| 87 | - | for i, entry := range histEntries { | |
| 88 | - | entries[i] = entry | |
| 89 | - | } | |
| 90 | - | } else { | |
| 91 | - | // Use original method for backward compatibility | |
| 92 | - | histEntries, err := h.browserService.GetRecentHistory(ctx, limit) | |
| 93 | - | if err != nil { | |
| 94 | - | return constants.ContentTypeJSON, []byte("[]"), true | |
| 95 | - | } | |
| 96 | - | // Convert to interface slice for JSON marshaling | |
| 97 | - | entries = make([]interface{}, len(histEntries)) | |
| 98 | - | for i, entry := range histEntries { | |
| 99 | - | entries[i] = entry | |
| 100 | - | } | |
| 101 | - | } | |
| 102 | - | ||
| 103 | - | b, _ := json.Marshal(entries) | |
| 104 | - | return constants.ContentTypeJSON, b, true | |
| 105 | - | } | |
| 106 | - | ||
| 107 | - | // HandleHistorySearch handles GET /history/search endpoint | |
| 108 | - | func (h *Handler) HandleHistorySearch(u *neturl.URL) (string, []byte, bool) { | |
| 109 | - | log.Printf("[api] GET /history/search%s", u.RawQuery) | |
| 110 | - | q := u.Query() | |
| 111 | - | query := q.Get("q") | |
| 112 | - | limit := 50 | |
| 113 | - | if l := q.Get("limit"); l != "" { | |
| 114 | - | if n, err := strconv.Atoi(l); err == nil && n > 0 { | |
| 115 | - | limit = n | |
| 116 | - | } | |
| 117 | - | } | |
| 118 | - | ctx := context.Background() | |
| 119 | - | entries, err := h.browserService.SearchHistory(ctx, query, limit) | |
| 120 | - | if err != nil { | |
| 121 | - | return constants.ContentTypeJSON, []byte("[]"), true | |
| 122 | - | } | |
| 123 | - | b, _ := json.Marshal(entries) | |
| 124 | - | return constants.ContentTypeJSON, b, true | |
| 125 | - | } | |
| 126 | - | ||
| 127 | - | // HandleHistoryStats handles GET /history/stats endpoint | |
| 128 | - | func (h *Handler) HandleHistoryStats() (string, []byte, bool) { | |
| 129 | - | log.Printf("[api] GET /history/stats") | |
| 130 | - | ctx := context.Background() | |
| 131 | - | stats, err := h.browserService.GetHistoryStats(ctx) | |
| 132 | - | if err != nil { | |
| 133 | - | return constants.ContentTypeJSON, []byte("{}"), true | |
| 134 | - | } | |
| 135 | - | b, _ := json.Marshal(stats) | |
| 136 | - | return constants.ContentTypeJSON, b, true | |
| 137 | - | } | |
| 138 | - | ||
| 139 | - | // HandleHistoryDelete handles GET /history/delete endpoint | |
| 140 | - | func (h *Handler) HandleHistoryDelete(u *neturl.URL) (string, []byte, bool) { | |
| 141 | - | log.Printf("[api] GET /history/delete%s", u.RawQuery) | |
| 142 | - | q := u.Query() | |
| 143 | - | idStr := q.Get("id") | |
| 144 | - | if idStr == "" { | |
| 145 | - | return constants.ContentTypeJSON, []byte(`{"error":"id parameter required"}`), true | |
| 146 | - | } | |
| 147 | - | id, err := strconv.ParseInt(idStr, 10, 64) | |
| 148 | - | if err != nil { | |
| 149 | - | return constants.ContentTypeJSON, []byte(`{"error":"invalid id parameter"}`), true | |
| 150 | - | } | |
| 151 | - | ctx := context.Background() | |
| 152 | - | err = h.browserService.DeleteHistoryEntry(ctx, id) | |
| 153 | - | if err != nil { | |
| 154 | - | return constants.ContentTypeJSON, []byte(`{"error":"failed to delete entry"}`), true | |
| 155 | - | } | |
| 156 | - | return constants.ContentTypeJSON, []byte(`{"success":true}`), true | |
| 157 | - | } | |
| 158 | - | ||
| 159 | - | // HandleDefault returns empty JSON for unknown endpoints | |
| 160 | - | func (h *Handler) HandleDefault() (string, []byte, bool) { | |
| 161 | - | return constants.ContentTypeJSON, []byte("{}"), true | |
| 162 | - | } | |
| @@ -1,162 +0,0 @@ | |||||
| 1 | - | package api | |||
| 2 | - | ||||
| 3 | - | import ( | |||
| 4 | - | "context" | |||
| 5 | - | "encoding/json" | |||
| 6 | - | "log" | |||
| 7 | - | neturl "net/url" | |||
| 8 | - | "strconv" | |||
| 9 | - | ||||
| 10 | - | "github.com/bnema/dumber/internal/app/constants" | |||
| 11 | - | "github.com/bnema/dumber/internal/config" | |||
| 12 | - | "github.com/bnema/dumber/services" | |||
| 13 | - | ) | |||
| 14 | - | ||||
| 15 | - | // Handler provides API endpoint handling functionality | |||
| 16 | - | type Handler struct { | |||
| 17 | - | browserService *services.BrowserService | |||
| 18 | - | } | |||
| 19 | - | ||||
| 20 | - | // NewHandler creates a new API handler | |||
| 21 | - | func NewHandler(browserService *services.BrowserService) *Handler { | |||
| 22 | - | return &Handler{ | |||
| 23 | - | browserService: browserService, | |||
| 24 | - | } | |||
| 25 | - | } | |||
| 26 | - | ||||
| 27 | - | // HandleRenderingStatus handles GET /rendering/status endpoint | |||
| 28 | - | func (h *Handler) HandleRenderingStatus(cfg *config.Config) (string, []byte, bool) { | |||
| 29 | - | log.Printf("[api] GET /rendering/status") | |||
| 30 | - | // Report configured rendering mode; runtime GPU state depends on WebKit internals | |||
| 31 | - | resp := struct { | |||
| 32 | - | Mode string `json:"mode"` | |||
| 33 | - | }{Mode: string(cfg.RenderingMode)} | |||
| 34 | - | b, _ := json.Marshal(resp) | |||
| 35 | - | return constants.ContentTypeJSON, b, true | |||
| 36 | - | } | |||
| 37 | - | ||||
| 38 | - | // HandleConfig handles GET /config endpoint | |||
| 39 | - | func (h *Handler) HandleConfig(cfg *config.Config) (string, []byte, bool) { | |||
| 40 | - | log.Printf("[api] GET /config") | |||
| 41 | - | // Build config info | |||
| 42 | - | cfgPath, _ := config.GetConfigFile() | |||
| 43 | - | info := struct { | |||
| 44 | - | ConfigPath string `json:"config_path"` | |||
| 45 | - | DatabasePath string `json:"database_path"` | |||
| 46 | - | SearchShortcuts map[string]config.SearchShortcut `json:"search_shortcuts"` | |||
| 47 | - | Appearance config.AppearanceConfig `json:"appearance"` | |||
| 48 | - | }{ | |||
| 49 | - | ConfigPath: cfgPath, | |||
| 50 | - | DatabasePath: cfg.Database.Path, | |||
| 51 | - | SearchShortcuts: cfg.SearchShortcuts, | |||
| 52 | - | Appearance: cfg.Appearance, | |||
| 53 | - | } | |||
| 54 | - | b, _ := json.Marshal(info) | |||
| 55 | - | return constants.ContentTypeJSON, b, true | |||
| 56 | - | } | |||
| 57 | - | ||||
| 58 | - | // HandleHistoryRecent handles GET /history/recent endpoint | |||
| 59 | - | func (h *Handler) HandleHistoryRecent(u *neturl.URL) (string, []byte, bool) { | |||
| 60 | - | log.Printf("[api] GET /history/recent%s", u.RawQuery) | |||
| 61 | - | // Parse limit and offset | |||
| 62 | - | q := u.Query() | |||
| 63 | - | limit := 20 | |||
| 64 | - | if l := q.Get("limit"); l != "" { | |||
| 65 | - | if n, err := strconv.Atoi(l); err == nil && n > 0 { | |||
| 66 | - | limit = n | |||
| 67 | - | } | |||
| 68 | - | } | |||
| 69 | - | offset := 0 | |||
| 70 | - | if o := q.Get("offset"); o != "" { | |||
| 71 | - | if n, err := strconv.Atoi(o); err == nil && n >= 0 { | |||
| 72 | - | offset = n | |||
| 73 | - | } | |||
| 74 | - | } | |||
| 75 | - | ||||
| 76 | - | ctx := context.Background() | |||
| 77 | - | var entries []interface{} | |||
| 78 | - | ||||
| 79 | - | // Use paginated version if offset is provided | |||
| 80 | - | if offset > 0 || q.Has("offset") { | |||
| 81 | - | histEntries, err := h.browserService.GetRecentHistoryWithOffset(ctx, limit, offset) | |||
| 82 | - | if err != nil { | |||
| 83 | - | return constants.ContentTypeJSON, []byte("[]"), true | |||
| 84 | - | } | |||
| 85 | - | // Convert to interface slice for JSON marshaling | |||
| 86 | - | entries = make([]interface{}, len(histEntries)) | |||
| 87 | - | for i, entry := range histEntries { | |||
| 88 | - | entries[i] = entry | |||
| 89 | - | } | |||
| 90 | - | } else { | |||
| 91 | - | // Use original method for backward compatibility | |||
| 92 | - | histEntries, err := h.browserService.GetRecentHistory(ctx, limit) | |||
| 93 | - | if err != nil { | |||
| 94 | - | return constants.ContentTypeJSON, []byte("[]"), true | |||
| 95 | - | } | |||
| 96 | - | // Convert to interface slice for JSON marshaling | |||
| 97 | - | entries = make([]interface{}, len(histEntries)) | |||
| 98 | - | for i, entry := range histEntries { | |||
| 99 | - | entries[i] = entry | |||
| 100 | - | } | |||
| 101 | - | } | |||
| 102 | - | ||||
| 103 | - | b, _ := json.Marshal(entries) | |||
| 104 | - | return constants.ContentTypeJSON, b, true | |||
| 105 | - | } | |||
| 106 | - | ||||
| 107 | - | // HandleHistorySearch handles GET /history/search endpoint | |||
| 108 | - | func (h *Handler) HandleHistorySearch(u *neturl.URL) (string, []byte, bool) { | |||
| 109 | - | log.Printf("[api] GET /history/search%s", u.RawQuery) | |||
| 110 | - | q := u.Query() | |||
| 111 | - | query := q.Get("q") | |||
| 112 | - | limit := 50 | |||
| 113 | - | if l := q.Get("limit"); l != "" { | |||
| 114 | - | if n, err := strconv.Atoi(l); err == nil && n > 0 { | |||
| 115 | - | limit = n | |||
| 116 | - | } | |||
| 117 | - | } | |||
| 118 | - | ctx := context.Background() | |||
| 119 | - | entries, err := h.browserService.SearchHistory(ctx, query, limit) | |||
| 120 | - | if err != nil { | |||
| 121 | - | return constants.ContentTypeJSON, []byte("[]"), true | |||
| 122 | - | } | |||
| 123 | - | b, _ := json.Marshal(entries) | |||
| 124 | - | return constants.ContentTypeJSON, b, true | |||
| 125 | - | } | |||
| 126 | - | ||||
| 127 | - | // HandleHistoryStats handles GET /history/stats endpoint | |||
| 128 | - | func (h *Handler) HandleHistoryStats() (string, []byte, bool) { | |||
| 129 | - | log.Printf("[api] GET /history/stats") | |||
| 130 | - | ctx := context.Background() | |||
| 131 | - | stats, err := h.browserService.GetHistoryStats(ctx) | |||
| 132 | - | if err != nil { | |||
| 133 | - | return constants.ContentTypeJSON, []byte("{}"), true | |||
| 134 | - | } | |||
| 135 | - | b, _ := json.Marshal(stats) | |||
| 136 | - | return constants.ContentTypeJSON, b, true | |||
| 137 | - | } | |||
| 138 | - | ||||
| 139 | - | // HandleHistoryDelete handles GET /history/delete endpoint | |||
| 140 | - | func (h *Handler) HandleHistoryDelete(u *neturl.URL) (string, []byte, bool) { | |||
| 141 | - | log.Printf("[api] GET /history/delete%s", u.RawQuery) | |||
| 142 | - | q := u.Query() | |||
| 143 | - | idStr := q.Get("id") | |||
| 144 | - | if idStr == "" { | |||
| 145 | - | return constants.ContentTypeJSON, []byte(`{"error":"id parameter required"}`), true | |||
| 146 | - | } | |||
| 147 | - | id, err := strconv.ParseInt(idStr, 10, 64) | |||
| 148 | - | if err != nil { | |||
| 149 | - | return constants.ContentTypeJSON, []byte(`{"error":"invalid id parameter"}`), true | |||
| 150 | - | } | |||
| 151 | - | ctx := context.Background() | |||
| 152 | - | err = h.browserService.DeleteHistoryEntry(ctx, id) | |||
| 153 | - | if err != nil { | |||
| 154 | - | return constants.ContentTypeJSON, []byte(`{"error":"failed to delete entry"}`), true | |||
| 155 | - | } | |||
| 156 | - | return constants.ContentTypeJSON, []byte(`{"success":true}`), true | |||
| 157 | - | } | |||
| 158 | - | ||||
| 159 | - | // HandleDefault returns empty JSON for unknown endpoints | |||
| 160 | - | func (h *Handler) HandleDefault() (string, []byte, bool) { | |||
| 161 | - | return constants.ContentTypeJSON, []byte("{}"), true | |||
| 162 | - | } | |||
M internal/app/api/scheme.go +0 -43
| @@ -16,7 +16,6 @@ import ( | |||
| 16 | 16 | // SchemeHandler handles custom dumb:// scheme resolution | |
| 17 | 17 | type SchemeHandler struct { | |
| 18 | 18 | assets embed.FS | |
| 19 | - | apiHandler *Handler | |
| 20 | 19 | parserService *services.ParserService | |
| 21 | 20 | browserService *services.BrowserService | |
| 22 | 21 | } | |
| @@ -29,7 +28,6 @@ func NewSchemeHandler( | |||
| 29 | 28 | ) *SchemeHandler { | |
| 30 | 29 | return &SchemeHandler{ | |
| 31 | 30 | assets: assets, | |
| 32 | - | apiHandler: NewHandler(browserService), | |
| 33 | 31 | parserService: parserService, | |
| 34 | 32 | browserService: browserService, | |
| 35 | 33 | } | |
| @@ -47,51 +45,10 @@ func (s *SchemeHandler) Handle(uri string, cfg *config.Config) (string, []byte, | |||
| 47 | 45 | return "", nil, false | |
| 48 | 46 | } | |
| 49 | 47 | ||
| 50 | - | // API routes | |
| 51 | - | if u.Host == "api" || strings.HasPrefix(u.Opaque, "api") || strings.HasPrefix(u.Path, "/api") { | |
| 52 | - | return s.handleAPIRoute(u, cfg) | |
| 53 | - | } | |
| 54 | - | ||
| 55 | 48 | // Static assets | |
| 56 | 49 | return s.handleAsset(u) | |
| 57 | 50 | } | |
| 58 | 51 | ||
| 59 | - | // handleAPIRoute processes API requests | |
| 60 | - | func (s *SchemeHandler) handleAPIRoute(u *neturl.URL, cfg *config.Config) (string, []byte, bool) { | |
| 61 | - | // Normalize path for opaque or hierarchical forms | |
| 62 | - | path := u.Path | |
| 63 | - | if path == "" && u.Opaque != "" { | |
| 64 | - | // e.g., dumb:api/config or dumb:api/history/recent | |
| 65 | - | parts := strings.SplitN(u.Opaque, ":", constants.ColonSplitParts) | |
| 66 | - | if len(parts) == constants.ColonSplitParts { | |
| 67 | - | path = "/" + parts[1] | |
| 68 | - | } | |
| 69 | - | } | |
| 70 | - | if strings.HasPrefix(path, "/api/") { | |
| 71 | - | path = strings.TrimPrefix(path, "/api") | |
| 72 | - | } | |
| 73 | - | if path == "/api" { | |
| 74 | - | path = "/" | |
| 75 | - | } | |
| 76 | - | ||
| 77 | - | switch { | |
| 78 | - | case strings.HasPrefix(path, "/rendering/status"): | |
| 79 | - | return s.apiHandler.HandleRenderingStatus(cfg) | |
| 80 | - | case strings.HasPrefix(path, "/config"): | |
| 81 | - | return s.apiHandler.HandleConfig(cfg) | |
| 82 | - | case strings.HasPrefix(path, "/history/recent"): | |
| 83 | - | return s.apiHandler.HandleHistoryRecent(u) | |
| 84 | - | case strings.HasPrefix(path, "/history/search"): | |
| 85 | - | return s.apiHandler.HandleHistorySearch(u) | |
| 86 | - | case strings.HasPrefix(path, "/history/stats"): | |
| 87 | - | return s.apiHandler.HandleHistoryStats() | |
| 88 | - | case strings.HasPrefix(path, "/history/delete"): | |
| 89 | - | return s.apiHandler.HandleHistoryDelete(u) | |
| 90 | - | default: | |
| 91 | - | return s.apiHandler.HandleDefault() | |
| 92 | - | } | |
| 93 | - | } | |
| 94 | - | ||
| 95 | 52 | // handleAsset serves static assets from embedded filesystem | |
| 96 | 53 | func (s *SchemeHandler) handleAsset(u *neturl.URL) (string, []byte, bool) { | |
| 97 | 54 | // Resolve target path inside embed FS | |
| @@ -16,7 +16,6 @@ import ( | |||||
| 16 | // SchemeHandler handles custom dumb:// scheme resolution | 16 | // SchemeHandler handles custom dumb:// scheme resolution | ||
| 17 | type SchemeHandler struct { | 17 | type SchemeHandler struct { | ||
| 18 | assets embed.FS | 18 | assets embed.FS | ||
| 19 | - | apiHandler *Handler | |||
| 20 | parserService *services.ParserService | 19 | parserService *services.ParserService | ||
| 21 | browserService *services.BrowserService | 20 | browserService *services.BrowserService | ||
| 22 | } | 21 | } | ||
| @@ -29,7 +28,6 @@ func NewSchemeHandler( | |||||
| 29 | ) *SchemeHandler { | 28 | ) *SchemeHandler { | ||
| 30 | return &SchemeHandler{ | 29 | return &SchemeHandler{ | ||
| 31 | assets: assets, | 30 | assets: assets, | ||
| 32 | - | apiHandler: NewHandler(browserService), | |||
| 33 | parserService: parserService, | 31 | parserService: parserService, | ||
| 34 | browserService: browserService, | 32 | browserService: browserService, | ||
| 35 | } | 33 | } | ||
| @@ -47,51 +45,10 @@ func (s *SchemeHandler) Handle(uri string, cfg *config.Config) (string, []byte, | |||||
| 47 | return "", nil, false | 45 | return "", nil, false | ||
| 48 | } | 46 | } | ||
| 49 | 47 | ||||
| 50 | - | // API routes | |||
| 51 | - | if u.Host == "api" || strings.HasPrefix(u.Opaque, "api") || strings.HasPrefix(u.Path, "/api") { | |||
| 52 | - | return s.handleAPIRoute(u, cfg) | |||
| 53 | - | } | |||
| 54 | - | ||||
| 55 | // Static assets | 48 | // Static assets | ||
| 56 | return s.handleAsset(u) | 49 | return s.handleAsset(u) | ||
| 57 | } | 50 | } | ||
| 58 | 51 | ||||
| 59 | - | // handleAPIRoute processes API requests | |||
| 60 | - | func (s *SchemeHandler) handleAPIRoute(u *neturl.URL, cfg *config.Config) (string, []byte, bool) { | |||
| 61 | - | // Normalize path for opaque or hierarchical forms | |||
| 62 | - | path := u.Path | |||
| 63 | - | if path == "" && u.Opaque != "" { | |||
| 64 | - | // e.g., dumb:api/config or dumb:api/history/recent | |||
| 65 | - | parts := strings.SplitN(u.Opaque, ":", constants.ColonSplitParts) | |||
| 66 | - | if len(parts) == constants.ColonSplitParts { | |||
| 67 | - | path = "/" + parts[1] | |||
| 68 | - | } | |||
| 69 | - | } | |||
| 70 | - | if strings.HasPrefix(path, "/api/") { | |||
| 71 | - | path = strings.TrimPrefix(path, "/api") | |||
| 72 | - | } | |||
| 73 | - | if path == "/api" { | |||
| 74 | - | path = "/" | |||
| 75 | - | } | |||
| 76 | - | ||||
| 77 | - | switch { | |||
| 78 | - | case strings.HasPrefix(path, "/rendering/status"): | |||
| 79 | - | return s.apiHandler.HandleRenderingStatus(cfg) | |||
| 80 | - | case strings.HasPrefix(path, "/config"): | |||
| 81 | - | return s.apiHandler.HandleConfig(cfg) | |||
| 82 | - | case strings.HasPrefix(path, "/history/recent"): | |||
| 83 | - | return s.apiHandler.HandleHistoryRecent(u) | |||
| 84 | - | case strings.HasPrefix(path, "/history/search"): | |||
| 85 | - | return s.apiHandler.HandleHistorySearch(u) | |||
| 86 | - | case strings.HasPrefix(path, "/history/stats"): | |||
| 87 | - | return s.apiHandler.HandleHistoryStats() | |||
| 88 | - | case strings.HasPrefix(path, "/history/delete"): | |||
| 89 | - | return s.apiHandler.HandleHistoryDelete(u) | |||
| 90 | - | default: | |||
| 91 | - | return s.apiHandler.HandleDefault() | |||
| 92 | - | } | |||
| 93 | - | } | |||
| 94 | - | ||||
| 95 | // handleAsset serves static assets from embedded filesystem | 52 | // handleAsset serves static assets from embedded filesystem | ||
| 96 | func (s *SchemeHandler) handleAsset(u *neturl.URL) (string, []byte, bool) { | 53 | func (s *SchemeHandler) handleAsset(u *neturl.URL) (string, []byte, bool) { | ||
| 97 | // Resolve target path inside embed FS | 54 | // Resolve target path inside embed FS | ||