From 6da7f6dffde91026c2c3bf09194f9250bbbbbbd4 Mon Sep 17 00:00:00 2001 From: Amir Raminfar Date: Wed, 5 Feb 2025 10:23:34 -0800 Subject: [PATCH] fix: fixes broken download link when host name has : --- .../ContainerViewer/ContainerActionsToolbar.vue | 2 +- .../LogViewer/MultiContainerActionToolbar.vue | 2 +- internal/web/download.go | 10 +++++++++- internal/web/download_test.go | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/assets/components/ContainerViewer/ContainerActionsToolbar.vue b/assets/components/ContainerViewer/ContainerActionsToolbar.vue index 70ffdcac..df136bb4 100644 --- a/assets/components/ContainerViewer/ContainerActionsToolbar.vue +++ b/assets/components/ContainerViewer/ContainerActionsToolbar.vue @@ -169,7 +169,7 @@ const downloadParams = computed(() => const downloadUrl = computed(() => withBase( - `/api/containers/${container.host}:${container.id}/download?${new URLSearchParams(downloadParams.value).toString()}`, + `/api/containers/${container.host}~${container.id}/download?${new URLSearchParams(downloadParams.value).toString()}`, ), ); diff --git a/assets/components/LogViewer/MultiContainerActionToolbar.vue b/assets/components/LogViewer/MultiContainerActionToolbar.vue index 1e8fa5ba..47c742e5 100644 --- a/assets/components/LogViewer/MultiContainerActionToolbar.vue +++ b/assets/components/LogViewer/MultiContainerActionToolbar.vue @@ -97,7 +97,7 @@ const downloadParams = computed(() => const downloadUrl = computed(() => withBase( - `/api/containers/${containers.value.map((c) => c.host + ":" + c.id).join(",")}/download?${new URLSearchParams(downloadParams.value).toString()}`, + `/api/containers/${containers.value.map((c) => c.host + "~" + c.id).join(",")}/download?${new URLSearchParams(downloadParams.value).toString()}`, ), ); diff --git a/internal/web/download.go b/internal/web/download.go index b63675d0..55a86387 100644 --- a/internal/web/download.go +++ b/internal/web/download.go @@ -12,11 +12,13 @@ import ( "github.com/amir20/dozzle/internal/docker" "github.com/docker/docker/pkg/stdcopy" "github.com/go-chi/chi/v5" + "github.com/rs/zerolog/log" ) func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { hostIds := strings.Split(chi.URLParam(r, "hostIds"), ",") if len(hostIds) == 0 { + log.Error().Msg("no container ids provided") http.Error(w, "no container ids provided", http.StatusBadRequest) return } @@ -55,8 +57,9 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { // Process each container for _, hostId := range hostIds { - parts := strings.Split(hostId, ":") + parts := strings.Split(hostId, "~") if len(parts) != 2 { + log.Error().Msgf("invalid host id: %s", hostId) http.Error(w, fmt.Sprintf("invalid host id: %s", hostId), http.StatusBadRequest) return } @@ -65,6 +68,7 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { id := parts[1] containerService, err := h.multiHostService.FindContainer(host, id, usersFilter) if err != nil { + log.Error().Err(err).Msgf("error finding container %s", id) http.Error(w, fmt.Sprintf("error finding container %s: %v", id, err), http.StatusBadRequest) return } @@ -73,6 +77,7 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { fileName := fmt.Sprintf("%s-%s.log", containerService.Container.Name, nowFmt) f, err := zw.Create(fileName) if err != nil { + log.Error().Err(err).Msgf("error creating zip entry for container %s", id) http.Error(w, fmt.Sprintf("error creating zip entry: %v", err), http.StatusInternalServerError) return } @@ -80,6 +85,7 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { // Get container logs reader, err := containerService.RawLogs(r.Context(), time.Time{}, now, stdTypes) if err != nil { + log.Error().Err(err).Msgf("error getting logs for container %s", id) http.Error(w, fmt.Sprintf("error getting logs for container %s: %v", id, err), http.StatusInternalServerError) return } @@ -87,11 +93,13 @@ func (h *handler) downloadLogs(w http.ResponseWriter, r *http.Request) { // Copy logs directly to zip entry if containerService.Container.Tty { if _, err := io.Copy(f, reader); err != nil { + log.Error().Err(err).Msgf("error copying logs for container %s", id) http.Error(w, fmt.Sprintf("error copying logs for container %s: %v", id, err), http.StatusInternalServerError) return } } else { if _, err := stdcopy.StdCopy(f, f, reader); err != nil { + log.Error().Err(err).Msgf("error copying logs for container %s", id) http.Error(w, fmt.Sprintf("error copying logs for container %s: %v", id, err), http.StatusInternalServerError) return } diff --git a/internal/web/download_test.go b/internal/web/download_test.go index eae17f08..712e04c8 100644 --- a/internal/web/download_test.go +++ b/internal/web/download_test.go @@ -16,7 +16,7 @@ import ( func Test_handler_download_logs(t *testing.T) { id := "123456" - req, err := http.NewRequest("GET", "/api/containers/localhost:"+id+"/download?stdout=1", nil) + req, err := http.NewRequest("GET", "/api/containers/localhost~"+id+"/download?stdout=1", nil) require.NoError(t, err, "NewRequest should not return an error.") mockedClient := new(MockedClient)