all repos — gopipe @ 8223ef17cd00edc14c764e8f9874a05ee2073d0b

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	format := getFormat(*video, formatID)
31	if format == nil {
32		http.Error(w, err500, http.StatusInternalServerError)
33		return
34	}
35
36	key := fmt.Sprintf("%s:%d", videoID, formatID)
37	content, err := g.PKS.Get(key)
38	if err == nil && content != nil {
39		log.Println("Using cached content for ", key)
40		w.Header().Set("Content-Type", "video/mp4")
41		w.Header().Set("Content-Length", strconv.Itoa(content.Len()))
42		w.Write(content.Bytes())
43		return
44	}
45
46	res, err := g.C.Get(format.URL)
47	if err != nil {
48		http.Error(w, err500, http.StatusInternalServerError)
49		return
50	}
51	defer res.Body.Close()
52
53	w.Header().Set("Content-Type", res.Header.Get("Content-Type"))
54	w.Header().Set("Content-Length", res.Header.Get("Content-Length"))
55
56	pr, pw := io.Pipe()
57
58	// Save the content to the cache asynchronously
59	go func() {
60		var buf bytes.Buffer
61		_, err := io.Copy(&buf, pr)
62		if err != nil {
63			log.Println("Error while copying to buffer for cache:", err)
64			return
65		}
66
67		g.PKS.Set(key, buf, 5*time.Minute)
68		pw.Close()
69	}()
70
71	// Stream the content to the client while it's being downloaded and piped
72	_, err = io.Copy(io.MultiWriter(w, pw), res.Body)
73	if err != nil {
74		http.Error(w, err500, http.StatusInternalServerError)
75		return
76	}
77}