feat: direct download via streaming
This commit is contained in:
		
							parent
							
								
									d50e88d1f9
								
							
						
					
					
						commit
						61502ea2f6
					
				
							
								
								
									
										104
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								main.go
									
									
									
									
									
								
							@ -2,10 +2,14 @@ package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"html/template"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"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() {
 | 
			
		||||
    
 | 
			
		||||
    log.Println("[ init ] Starting...")
 | 
			
		||||
@ -195,6 +218,7 @@ func main() {
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            ctx.DownloadURL = downloadURL
 | 
			
		||||
            w.Header().Add("Hx-Redirect", fmt.Sprintf("/download-direct?URL=%s", ctx.DownloadURL))
 | 
			
		||||
            err = templates.ExecuteTemplate(w,"download-result.html", ctx)
 | 
			
		||||
            if err != nil {
 | 
			
		||||
                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) {
 | 
			
		||||
        ctx := NewContext(r)
 | 
			
		||||
        formats := []DownloadFormats{}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user