feat: direct download via streaming

This commit is contained in:
HeshamTB 2023-09-14 20:13:32 +03:00
parent d50e88d1f9
commit 61502ea2f6

104
main.go
View File

@ -2,10 +2,14 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"html/template" "html/template"
"io"
"log" "log"
"net/http" "net/http"
"net/url"
"os" "os"
"strings"
"time" "time"
) )
@ -121,6 +125,25 @@ func NewContext(r *http.Request) *Context {
} }
} }
func handleToAudio(ctx *Context, w http.ResponseWriter) http.ResponseWriter {
log.Println("User requested audio")
w.WriteHeader(400)
jsonMsg, err := json.Marshal(
apiMessageResponse{
Message: "Audio only is not implemented",
},
)
if err != nil {
log.Println(err.Error())
w.WriteHeader(500)
}
w.Write(jsonMsg)
return w
}
func init() { func init() {
log.Println("[ init ] Starting...") log.Println("[ init ] Starting...")
@ -195,6 +218,7 @@ func main() {
} }
ctx.DownloadURL = downloadURL ctx.DownloadURL = downloadURL
w.Header().Add("Hx-Redirect", fmt.Sprintf("/download-direct?URL=%s", ctx.DownloadURL))
err = templates.ExecuteTemplate(w,"download-result.html", ctx) err = templates.ExecuteTemplate(w,"download-result.html", ctx)
if err != nil { if err != nil {
log.Println(err.Error()) log.Println(err.Error())
@ -206,6 +230,86 @@ func main() {
}, },
) )
handler.HandleFunc(
"/download-direct",
func(w http.ResponseWriter, r *http.Request) {
ctx := NewContext(r)
if r.Method != "GET" {
w.WriteHeader(400)
return
}
userURL := r.URL.Query().Get("URL")
urlRaw := strings.TrimLeft(r.URL.RawQuery, "URL=")
urlRaw, err := url.QueryUnescape(urlRaw)
if err != nil {
log.Println("Can not unescape url")
w.WriteHeader(400)
return
}
userURL = urlRaw
if userURL == "" {
w.WriteHeader(400)
ctx.StatusCode = 400
if err := templates.ExecuteTemplate(w,"download-result.html", ctx); err != nil {
log.Println(err.Error())
}
return
}
log.Println("Got url: ", userURL, "for direct download")
ctx.DownloadURL = userURL
req, err := http.NewRequest("GET", ctx.DownloadURL, nil)
if err != nil {
ctx.StatusCode = 500
ctx.Err = &err
if err := templates.ExecuteTemplate(w,"download-result.html", ctx); err != nil {
log.Println(err.Error())
}
return
}
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0")
client := http.Client{}
dataRequest, err := client.Do(req)
if err != nil {
log.Println(err.Error())
ctx.StatusCode = 500
ctx.Err = &err
if err := templates.ExecuteTemplate(w,"download-result.html", ctx); err != nil {
log.Println(err.Error())
}
return
}
defer dataRequest.Body.Close()
log.Printf("HTTP Client response: %v", dataRequest)
if dataRequest.StatusCode != 200 {
log.Println("Failed to get content for URL", userURL)
}
w.Header().Set("Content-Disposition", "attachment;filename=")
w.WriteHeader(206)
if dataRequest.ContentLength == 0 {
log.Println("Empty body from content url")
w.WriteHeader(500)
return
}
n, err := io.Copy(w, dataRequest.Body)
if err != nil {
log.Println(err.Error())
}
log.Printf("Copied %d bytes", n)
},
)
handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
ctx := NewContext(r) ctx := NewContext(r)
formats := []DownloadFormats{} formats := []DownloadFormats{}