all repos — gopipe @ 83cd0bd9237351f9da3ef236617c2f915f2277c4

Embed YouTube videos on Telegram, Discord and more!

src/app/proxy.go (view raw)

 1package app
 2
 3import (
 4	"bytes"
 5	"fmt"
 6	"io"
 7	"log"
 8	"net/http"
 9	"strconv"
10	"time"
11
12	g "github.com/birabittoh/gopipe/src/globals"
13)
14
15func proxyHandler(w http.ResponseWriter, r *http.Request) {
16	if !g.Proxy {
17		http.Error(w, err404, http.StatusNotFound)
18		return
19	}
20
21	videoID := r.PathValue("videoID")
22	formatID := getFormatID(r.PathValue("formatID"))
23
24	video, err := g.KS.Get(videoID)
25	if err != nil || video == nil {
26		http.Error(w, err404, http.StatusNotFound)
27		return
28	}
29
30	if video.ID == emptyVideo.ID {
31		http.Error(w, err500, http.StatusInternalServerError)
32		return
33	}
34
35	format := getFormat(*video, formatID)
36	if format == nil {
37		http.Error(w, err500, http.StatusInternalServerError)
38		return
39	}
40
41	key := fmt.Sprintf("%s:%d", videoID, formatID)
42	content, err := g.PKS.Get(key)
43	if err == nil && content != nil {
44		log.Println("Using cached content for ", key)
45		w.Header().Set("Content-Type", "video/mp4")
46		w.Header().Set("Content-Length", strconv.Itoa(content.Len()))
47		w.Write(content.Bytes())
48		return
49	}
50
51	res, err := g.C.Get(format.URL)
52	if err != nil {
53		http.Error(w, err500, http.StatusInternalServerError)
54		return
55	}
56	defer res.Body.Close()
57
58	w.Header().Set("Content-Type", res.Header.Get("Content-Type"))
59	w.Header().Set("Content-Length", res.Header.Get("Content-Length"))
60
61	pr, pw := io.Pipe()
62
63	// Save the content to the cache asynchronously
64	go func() {
65		var buf bytes.Buffer
66		_, err := io.Copy(&buf, pr)
67		if err != nil {
68			log.Println("Error while copying to buffer for cache:", err)
69			return
70		}
71
72		g.PKS.Set(key, buf, 5*time.Minute)
73		pw.Close()
74	}()
75
76	// Stream the content to the client while it's being downloaded and piped
77	_, err = io.Copy(io.MultiWriter(w, pw), res.Body)
78	if err != nil {
79		http.Error(w, err500, http.StatusInternalServerError)
80		return
81	}
82}