Cleanup, snapshot all routes

This commit is contained in:
Tobias Gesellchen
2026-03-29 19:14:48 +02:00
parent a06657f3f5
commit 766671f02b
4 changed files with 272 additions and 36 deletions
+53 -36
View File
@@ -661,46 +661,58 @@ func setupRouter(server *handlers.Server) *chi.Mux {
r.Route("/bmx", func(r chi.Router) {
r.Get("/registry/v1/services", server.HandleBMXRegistry)
r.Get("/tunein/v1/playback/station/{stationID}", server.HandleTuneInPlayback)
r.Get("/tunein/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo)
r.Get("/tunein/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast)
r.Route("/tunein", func(r chi.Router) {
r.Get("/v1/playback/station/{stationID}", server.HandleTuneInPlayback)
r.Get("/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo)
r.Get("/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast)
})
r.Post("/orion/v1/playback/station/{data}", server.HandleOrionPlayback)
})
// Legacy or direct domain calls without /bmx prefix
r.Get("/registry/v1/services", server.HandleBMXRegistry)
r.Get("/tunein/v1/playback/station/{stationID}", server.HandleTuneInPlayback)
r.Get("/tunein/v1/playback/episodes/{podcastID}", server.HandleTuneInPodcastInfo)
r.Get("/tunein/v1/playback/episode/{podcastID}", server.HandleTuneInPlaybackPodcast)
r.Post("/orion/v1/playback/station/{data}", server.HandleOrionPlayback)
r.Get("/custom/v1/playback/{encodedURL}", server.HandleCustomPlayback)
r.Route("/streaming", func(r chi.Router) {
r.Get("/sourceproviders", server.HandleMargeSourceProviders)
r.Post("/account", server.HandleMargeCreateAccount)
r.Post("/account/login", server.HandleMargeLogin)
r.Route("/account/{account}/device", func(r chi.Router) {
r.Post("/", server.HandleMargeAddDevice)
r.Post("/{device}", server.HandleMargeAddDevice)
r.Route("/account/{account}", func(r chi.Router) {
r.Get("/emailaddress", server.HandleMargeGetEmailAddress)
r.Get("/full", server.HandleMargeAccountFull)
r.Get("/provider_settings", server.HandleMargeProviderSettings)
r.Route("/device", func(r chi.Router) {
r.Post("/", server.HandleMargeAddDevice)
r.Post("/{device}", server.HandleMargeAddDevice)
})
r.Route("/device/{device}", func(r chi.Router) {
r.Get("/presets", server.HandleMargePresets)
r.Post("/presets/{presetNumber}", server.HandleMargeUpdatePreset)
r.Get("/recent", server.HandleMargeRecents)
r.Post("/recent", server.HandleMargeAddRecent)
r.Get("/group", server.HandleMargeDeviceGroup)
r.Get("/group/", server.HandleMargeDeviceGroup)
r.Get("/group/server", server.HandleMargeDeviceGroupServer)
r.Get("/group/member", server.HandleMargeDeviceGroupMember)
})
})
r.Get("/account/{account}/device/{device}/recent", server.HandleMargeRecents)
r.Post("/account/{account}/device/{device}/recent", server.HandleMargeAddRecent)
r.Get("/account/{account}/device/{device}/presets", server.HandleMargePresets)
r.Post("/account/{account}/device/{device}/presets/{presetNumber}", server.HandleMargeUpdatePreset)
r.Post("/support/power_on", server.HandleMargePowerOn)
r.Get("/account/{account}/provider_settings", server.HandleMargeProviderSettings)
r.Get("/device/{device}/streaming_token", server.HandleMargeStreamingToken)
r.Post("/support/customersupport", server.HandleMargeCustomerSupport)
r.Get("/device_setting/account/{account}/device/{device}/device_settings", server.HandleMargeGetDeviceSettings)
r.Get("/account/{account}/device/{device}/group", server.HandleMargeDeviceGroup)
r.Get("/account/{account}/device/{device}/group/", server.HandleMargeDeviceGroup)
r.Get("/account/{account}/device/{device}/group/server", server.HandleMargeDeviceGroupServer)
r.Get("/account/{account}/device/{device}/group/member", server.HandleMargeDeviceGroupMember)
r.Post("/device_setting/account/{account}/device/{device}/device_settings", server.HandleMargeUpdateDeviceSettings)
r.Get("/account/{account}/emailaddress", server.HandleMargeGetEmailAddress)
r.Get("/account/{account}/full", server.HandleMargeAccountFull)
r.Get("/software/update/account/{account}", server.HandleMargeSoftwareUpdate)
r.Route("/support", func(r chi.Router) {
r.Post("/power_on", server.HandleMargePowerOn)
r.Post("/customersupport", server.HandleMargeCustomerSupport)
})
r.Route("/stats", func(r chi.Router) {
r.Post("/usage", server.HandleUsageStats)
r.Post("/error", server.HandleErrorStats)
@@ -708,17 +720,22 @@ func setupRouter(server *handlers.Server) *chi.Mux {
})
r.Route("/accounts", func(r chi.Router) {
r.Get("/{account}/full", server.HandleMargeAccountFull)
r.Get("/{account}/devices/{device}/presets", server.HandleMargePresets)
r.Post("/{account}/devices/{device}/presets/{presetNumber}", server.HandleMargeUpdatePreset)
r.Get("/{account}/devices/{device}/recents", server.HandleMargeRecents)
r.Post("/{account}/devices/{device}/recents", server.HandleMargeAddRecent)
r.Post("/{account}/devices", server.HandleMargeAddDevice)
r.Delete("/{account}/devices/{device}", server.HandleMargeRemoveDevice)
r.Get("/{account}/devices/{device}/group", server.HandleMargeDeviceGroup)
r.Get("/{account}/devices/{device}/group/", server.HandleMargeDeviceGroup)
r.Get("/{account}/devices/{device}/group/server", server.HandleMargeDeviceGroupServer)
r.Get("/{account}/devices/{device}/group/member", server.HandleMargeDeviceGroupMember)
r.Route("/{account}", func(r chi.Router) {
r.Get("/full", server.HandleMargeAccountFull)
r.Post("/devices", server.HandleMargeAddDevice)
r.Delete("/devices/{device}", server.HandleMargeRemoveDevice)
r.Get("/devices/{device}/group", server.HandleMargeDeviceGroup)
r.Get("/devices/{device}/group/", server.HandleMargeDeviceGroup)
r.Get("/devices/{device}/group/server", server.HandleMargeDeviceGroupServer)
r.Get("/devices/{device}/group/member", server.HandleMargeDeviceGroupMember)
r.Get("/devices/{device}/presets", server.HandleMargePresets)
r.Get("/devices/{device}/recents", server.HandleMargeRecents)
r.Post("/devices/{device}/presets/{presetNumber}", server.HandleMargeUpdatePreset)
r.Post("/devices/{device}/recents", server.HandleMargeAddRecent)
})
})
r.Get("/updates/soundtouch", server.HandleMargeSoftwareUpdate)
+104
View File
@@ -0,0 +1,104 @@
package main
import (
"fmt"
"net/http"
"os"
"reflect"
"runtime"
"sort"
"strings"
"testing"
"github.com/gesellix/bose-soundtouch/pkg/service/handlers"
"github.com/go-chi/chi/v5"
)
func TestPrintRoutes(t *testing.T) {
// Initialize a minimal server to get the router
server := handlers.NewServer(nil, nil, "http://localhost:8000", true, true, true)
r := setupRouter(server)
var routes []string
walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
route = strings.ReplaceAll(route, "/*/", "/")
handlerName := runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name()
// Clean up the handler name (remove package path)
// For example, "github.com/gesellix/bose-soundtouch/cmd/soundtouch-service.setupRouter.func1"
// or "command-line-arguments.setupRouter.func1"
// or "main.setupRouter.func1"
parts := strings.Split(handlerName, "/")
if len(parts) > 0 {
handlerName = parts[len(parts)-1]
}
// Now we might have "soundtouch-service.setupRouter.func1"
// or "command-line-arguments.setupRouter.func1"
// or "main.setupRouter.func1"
// Let's remove the first part if it's a known varying package name
if idx := strings.Index(handlerName, "setupRouter"); idx != -1 {
handlerName = handlerName[idx:]
}
// In case it's not setupRouter but still has a package prefix
for {
dotIdx := strings.Index(handlerName, ".")
if dotIdx == -1 {
break
}
prefix := handlerName[:dotIdx]
if prefix == "main" || prefix == "command-line-arguments" || strings.Contains(prefix, "soundtouch-service") {
handlerName = handlerName[dotIdx+1:]
} else {
break
}
}
// Also remove any ".funcN" suffix if it's an anonymous function
if idx := strings.Index(handlerName, ".func"); idx != -1 {
handlerName = handlerName[:idx]
}
routes = append(routes, fmt.Sprintf("%-8s %-60s %s", method, route, handlerName))
return nil
}
if err := chi.Walk(r, walkFunc); err != nil {
t.Fatalf("Failed to walk routes: %v", err)
}
sort.Strings(routes)
output := strings.Join(routes, "\n") + "\n"
// Define snapshot path
snapshotPath := "testdata/router_routes.txt"
actualPath := "testdata/router_routes.actual.txt"
// Always write the current (actual) routes to a file
if err := os.WriteFile(actualPath, []byte(output), 0644); err != nil {
t.Fatalf("Failed to write actual routes: %v", err)
}
// Check if snapshot exists
if _, err := os.Stat(snapshotPath); os.IsNotExist(err) {
// Create testdata directory if it doesn't exist
if err := os.MkdirAll("testdata", 0755); err != nil {
t.Fatalf("Failed to create testdata directory: %v", err)
}
// Initial snapshot creation
if err := os.WriteFile(snapshotPath, []byte(output), 0644); err != nil {
t.Fatalf("Failed to write snapshot: %v", err)
}
t.Logf("Initial snapshot created at %s", snapshotPath)
return
}
// Read existing snapshot
existingOutput, err := os.ReadFile(snapshotPath)
if err != nil {
t.Fatalf("Failed to read snapshot: %v", err)
}
if string(existingOutput) != output {
t.Errorf("Router routes changed! Diff the snapshot at %s with %s", snapshotPath, actualPath)
}
}
@@ -0,0 +1 @@
*.actual.txt
+114
View File
@@ -0,0 +1,114 @@
CONNECT /oauth/* handlers.(*Server).HandleBoseProxy-fm
DELETE /accounts/{account}/devices/{device} handlers.(*Server).HandleMargeRemoveDevice-fm
DELETE /oauth/* handlers.(*Server).HandleBoseProxy-fm
DELETE /setup/devices/{deviceId} handlers.(*Server).HandleRemoveDevice-fm
DELETE /setup/dns-discoveries handlers.(*Server).HandleClearDNSDiscoveries-fm
DELETE /setup/interactions/sessions handlers.(*Server).HandleCleanupSessions-fm
DELETE /setup/interactions/sessions/{session} handlers.(*Server).HandleDeleteSession-fm
DELETE /setup/parity-mismatches handlers.(*Server).HandleClearParityMismatches-fm
GET / handlers.(*Server).HandleRoot-fm
GET /accounts/{account}/devices/{device}/group handlers.(*Server).HandleMargeDeviceGroup-fm
GET /accounts/{account}/devices/{device}/group/ handlers.(*Server).HandleMargeDeviceGroup-fm
GET /accounts/{account}/devices/{device}/group/member handlers.(*Server).HandleMargeDeviceGroupMember-fm
GET /accounts/{account}/devices/{device}/group/server handlers.(*Server).HandleMargeDeviceGroupServer-fm
GET /accounts/{account}/devices/{device}/presets handlers.(*Server).HandleMargePresets-fm
GET /accounts/{account}/devices/{device}/recents handlers.(*Server).HandleMargeRecents-fm
GET /accounts/{account}/full handlers.(*Server).HandleMargeAccountFull-fm
GET /bmx/registry/v1/services handlers.(*Server).HandleBMXRegistry-fm
GET /bmx/tunein/v1/playback/episode/{podcastID} handlers.(*Server).HandleTuneInPlaybackPodcast-fm
GET /bmx/tunein/v1/playback/episodes/{podcastID} handlers.(*Server).HandleTuneInPodcastInfo-fm
GET /bmx/tunein/v1/playback/station/{stationID} handlers.(*Server).HandleTuneInPlayback-fm
GET /custom/v1/playback/{encodedURL} handlers.(*Server).HandleCustomPlayback-fm
GET /customer/account/{account} handlers.(*Server).HandleMargeAccountProfile-fm
GET /docs/* handlers.(*Server).HandleDocs-fm
GET /favicon.ico setupRouter
GET /health handlers.(*Server).HandleHealth-fm
GET /media/* handlers.(*Server).HandleMedia
GET /mgmt/accounts/ handlers.(*Server).HandleMgmtListAccounts-fm
GET /mgmt/accounts/{accountId} handlers.(*Server).HandleMgmtAccountDetails-fm
GET /mgmt/accounts/{accountId}/speakers handlers.(*Server).HandleMgmtListSpeakers-fm
GET /mgmt/devices/{deviceId}/events handlers.(*Server).HandleMgmtDeviceEvents-fm
GET /mgmt/spotify/accounts handlers.(*Server).HandleMgmtSpotifyAccounts-fm
GET /mgmt/spotify/callback handlers.(*Server).HandleMgmtSpotifyCallback-fm
GET /mgmt/spotify/token handlers.(*Server).HandleMgmtSpotifyToken-fm
GET /oauth/* handlers.(*Server).HandleBoseProxy-fm
GET /proxy/* handlers.(*Server).HandleProxyRequest-fm
GET /setup/ca.crt handlers.(*Server).HandleGetCACert-fm
GET /setup/devices handlers.(*Server).HandleListDiscoveredDevices-fm
GET /setup/devices/{deviceId}/events handlers.(*Server).HandleGetDeviceEvents-fm
GET /setup/discovery-status handlers.(*Server).HandleGetDiscoveryStatus-fm
GET /setup/dns-discoveries handlers.(*Server).HandleGetDNSDiscoveries-fm
GET /setup/dns-discoveries/download handlers.(*Server).HandleDownloadDNSDiscoveries-fm
GET /setup/info/{deviceId} handlers.(*Server).HandleGetDeviceInfo-fm
GET /setup/interaction-content handlers.(*Server).HandleGetInteractionContent-fm
GET /setup/interaction-stats handlers.(*Server).HandleGetInteractionStats-fm
GET /setup/interactions handlers.(*Server).HandleListInteractions-fm
GET /setup/interactions/sessions/{session}/download handlers.(*Server).HandleDownloadSession-fm
GET /setup/parity-mismatches handlers.(*Server).HandleListParityMismatches-fm
GET /setup/proxy-settings handlers.(*Server).HandleGetProxySettings-fm
GET /setup/settings handlers.(*Server).HandleGetSettings-fm
GET /setup/summary/{deviceId} handlers.(*Server).HandleGetMigrationSummary-fm
GET /setup/version handlers.(*Server).HandleGetVersionInfo-fm
GET /streaming/account/{account}/device/{device}/group handlers.(*Server).HandleMargeDeviceGroup-fm
GET /streaming/account/{account}/device/{device}/group/ handlers.(*Server).HandleMargeDeviceGroup-fm
GET /streaming/account/{account}/device/{device}/group/member handlers.(*Server).HandleMargeDeviceGroupMember-fm
GET /streaming/account/{account}/device/{device}/group/server handlers.(*Server).HandleMargeDeviceGroupServer-fm
GET /streaming/account/{account}/device/{device}/presets handlers.(*Server).HandleMargePresets-fm
GET /streaming/account/{account}/device/{device}/recent handlers.(*Server).HandleMargeRecents-fm
GET /streaming/account/{account}/emailaddress handlers.(*Server).HandleMargeGetEmailAddress-fm
GET /streaming/account/{account}/full handlers.(*Server).HandleMargeAccountFull-fm
GET /streaming/account/{account}/provider_settings handlers.(*Server).HandleMargeProviderSettings-fm
GET /streaming/device/{device}/streaming_token handlers.(*Server).HandleMargeStreamingToken-fm
GET /streaming/device_setting/account/{account}/device/{device}/device_settings handlers.(*Server).HandleMargeGetDeviceSettings-fm
GET /streaming/software/update/account/{account} handlers.(*Server).HandleMargeSoftwareUpdate-fm
GET /streaming/sourceproviders handlers.(*Server).HandleMargeSourceProviders-fm
GET /updates/soundtouch handlers.(*Server).HandleMargeSoftwareUpdate-fm
GET /web/* setupRouter.(*Server).HandleWeb
HEAD /oauth/* handlers.(*Server).HandleBoseProxy-fm
OPTIONS /oauth/* handlers.(*Server).HandleBoseProxy-fm
PATCH /oauth/* handlers.(*Server).HandleBoseProxy-fm
POST /accounts/{account}/devices handlers.(*Server).HandleMargeAddDevice-fm
POST /accounts/{account}/devices/{device}/presets/{presetNumber} handlers.(*Server).HandleMargeUpdatePreset-fm
POST /accounts/{account}/devices/{device}/recents handlers.(*Server).HandleMargeAddRecent-fm
POST /bmx/orion/v1/playback/station/{data} handlers.(*Server).HandleOrionPlayback-fm
POST /customer/account/{account} handlers.(*Server).HandleMargeUpdateAccountProfile-fm
POST /customer/account/{account}/password handlers.(*Server).HandleMargeChangePassword-fm
POST /mgmt/accounts/{accountId}/language handlers.(*Server).HandleMgmtUpdateAccountLanguage-fm
POST /mgmt/accounts/{accountId}/provider-settings handlers.(*Server).HandleMgmtUpdateAccountProviderSetting-fm
POST /mgmt/spotify/confirm handlers.(*Server).HandleMgmtSpotifyConfirm-fm
POST /mgmt/spotify/entity handlers.(*Server).HandleMgmtSpotifyEntity-fm
POST /mgmt/spotify/init handlers.(*Server).HandleMgmtSpotifyInit-fm
POST /mgmt/spotify/prime handlers.(*Server).HandleMgmtPrimeDevice-fm
POST /oauth/* handlers.(*Server).HandleBoseProxy-fm
POST /oauth/device/{deviceID}/music/musicprovider/{sourceID}/token handlers.(*Server).HandleBoseLegacyToken-fm
POST /oauth/device/{deviceID}/music/musicprovider/{sourceID}/token/cs3 handlers.(*Server).HandleBoseToken-fm
POST /setup/backup/{deviceId} handlers.(*Server).HandleBackupConfig-fm
POST /setup/devices handlers.(*Server).HandleAddManualDevice-fm
POST /setup/discover handlers.(*Server).HandleTriggerDiscovery-fm
POST /setup/ensure-remote-services/{deviceId} handlers.(*Server).HandleEnsureRemoteServices-fm
POST /setup/migrate/{deviceId} handlers.(*Server).HandleMigrateDevice-fm
POST /setup/proxy-settings handlers.(*Server).HandleUpdateProxySettings-fm
POST /setup/reboot/{deviceId} handlers.(*Server).HandleRebootDevice-fm
POST /setup/remove-remote-services/{deviceId} handlers.(*Server).HandleRemoveRemoteServices-fm
POST /setup/revert/{deviceId} handlers.(*Server).HandleRevertMigration-fm
POST /setup/settings handlers.(*Server).HandleUpdateSettings-fm
POST /setup/sync/{deviceId} handlers.(*Server).HandleInitialSync-fm
POST /setup/test-connection/{deviceId} handlers.(*Server).HandleTestConnection-fm
POST /setup/test-dns/{deviceId} handlers.(*Server).HandleTestDNSRedirection-fm
POST /setup/test-hosts/{deviceId} handlers.(*Server).HandleTestHostsRedirection-fm
POST /setup/trust-ca/{deviceId} handlers.(*Server).HandleTrustCACert-fm
POST /streaming/account handlers.(*Server).HandleMargeCreateAccount-fm
POST /streaming/account/login handlers.(*Server).HandleMargeLogin-fm
POST /streaming/account/{account}/device/ handlers.(*Server).HandleMargeAddDevice-fm
POST /streaming/account/{account}/device/{device} handlers.(*Server).HandleMargeAddDevice-fm
POST /streaming/account/{account}/device/{device}/presets/{presetNumber} handlers.(*Server).HandleMargeUpdatePreset-fm
POST /streaming/account/{account}/device/{device}/recent handlers.(*Server).HandleMargeAddRecent-fm
POST /streaming/device_setting/account/{account}/device/{device}/device_settings handlers.(*Server).HandleMargeUpdateDeviceSettings-fm
POST /streaming/stats/error handlers.(*Server).HandleErrorStats-fm
POST /streaming/stats/usage handlers.(*Server).HandleUsageStats-fm
POST /streaming/support/customersupport handlers.(*Server).HandleMargeCustomerSupport-fm
POST /streaming/support/power_on handlers.(*Server).HandleMargePowerOn-fm
POST /v1/scmudc/{deviceId} handlers.(*Server).HandleAppEvents-fm
POST /v1/stapp/{deviceId} handlers.(*Server).HandleAppEvents-fm
PUT /oauth/* handlers.(*Server).HandleBoseProxy-fm
TRACE /oauth/* handlers.(*Server).HandleBoseProxy-fm