diff --git a/cmd/ytdl-web/download.go b/cmd/ytdl-web/download.go index cc15f3b..818d69c 100644 --- a/cmd/ytdl-web/download.go +++ b/cmd/ytdl-web/download.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "io" "log/slog" @@ -13,25 +14,26 @@ import ( "go.fifitido.net/ytdl-web/pkg/ytdl/metadata" ) -func getUrlParam(r *http.Request) (string, bool) { +func getUrlParam(r *http.Request) (string, error) { urlRaw := r.URL.Query().Get("url") if urlRaw == "" { - return "", false + return "", errors.New("url param not specified") } urlUnescaped, err := url.QueryUnescape(urlRaw) if err != nil || len(urlUnescaped) < 1 { - return "", false + return "", errors.New("invalid url") } - return urlUnescaped, true + return urlUnescaped, nil } func download(w http.ResponseWriter, r *http.Request) { ytdl := ytdl.Default() - videoUrl, ok := getUrlParam(r) - if !ok { + videoUrl, err := getUrlParam(r) + if err != nil { + slog.ErrorContext(r.Context(), "Failed to get video url param", slog.Any("error", err)) views.Render(w, r, views.Home(&views.Error{Message: "Invalid URL"})) return } @@ -47,15 +49,16 @@ func download(w http.ResponseWriter, r *http.Request) { func proxyDownload(w http.ResponseWriter, r *http.Request) { ytdl := ytdl.Default() - videoUrl, ok := getUrlParam(r) - if !ok { - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + videoUrl, err := getUrlParam(r) + if err != nil { + slog.ErrorContext(r.Context(), "Failed to get video url param", slog.Any("error", err)) + http.Error(w, "Video URL not specified or invalid URL", http.StatusBadRequest) return } formatId := r.URL.Query().Get("format") if formatId == "" { - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + http.Error(w, "Format ID not specified", http.StatusBadRequest) return } @@ -69,7 +72,8 @@ func proxyDownload(w http.ResponseWriter, r *http.Request) { index, err := strconv.Atoi(r.URL.Query().Get("index")) if err != nil || index < 0 || index >= len(videos) { - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + slog.Error("Failed to parse index", slog.Any("error", err), slog.Int("index", index), slog.Int("len", len(videos))) + http.Error(w, "Index not specified or invalid index", http.StatusBadRequest) return } @@ -82,8 +86,19 @@ func proxyDownload(w http.ResponseWriter, r *http.Request) { break } } + if format == nil { - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + for _, f := range video.OtherFormats { + if f.FormatID == formatId { + format = &f + break + } + } + } + + if format == nil { + slog.Error("Failed to find format", slog.String("format_id", formatId), slog.String("video_id", video.Meta.ID), slog.Int("index", index)) + http.Error(w, "Format not found", http.StatusBadRequest) return } @@ -97,6 +112,7 @@ func proxyDownload(w http.ResponseWriter, r *http.Request) { } read, write := io.Pipe() + defer write.Close() go func() { _, err := io.Copy(w, read) @@ -109,6 +125,4 @@ func proxyDownload(w http.ResponseWriter, r *http.Request) { slog.Error("Failed to download", slog.String("error", err.Error())) http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } - - write.Close() } diff --git a/devenv.nix b/devenv.nix index 780c365..646e5f8 100644 --- a/devenv.nix +++ b/devenv.nix @@ -1,4 +1,4 @@ -{ pkgs, lib, config, inputs, ... }: +{ pkgs, config, ... }: { # https://devenv.sh/basics/ diff --git a/pkg/views/downloads.templ b/pkg/views/downloads.templ index 095f339..9fb1584 100644 --- a/pkg/views/downloads.templ +++ b/pkg/views/downloads.templ @@ -31,7 +31,7 @@ templ videoFormatView(vm *DownloadsViewModel, vidIndex int, format metadata.Form Download (proxied) diff --git a/pkg/views/helpers.go b/pkg/views/helpers.go index de82a90..9b6b725 100644 --- a/pkg/views/helpers.go +++ b/pkg/views/helpers.go @@ -9,5 +9,5 @@ import ( ) func pathTo(ctx context.Context, path ...string) templ.SafeURL { - return templ.SafeURL(serverctx.BasePath(ctx) + "/" + strings.TrimPrefix(strings.Join(path, "/"), "/")) + return templ.SafeURL(strings.TrimSuffix(serverctx.BasePath(ctx), "/") + "/" + strings.TrimPrefix(strings.Join(path, "/"), "/")) }