all repos — fixyoutube-go @ aacf9865a2bfb0355680dd4e28b98e19d2b8400a

A better way to embed YouTube videos everywhere (inspired by FixTweet).

invidious/proxy.go (view raw)

 1package invidious
 2
 3import (
 4	"bytes"
 5	"io"
 6	"net/http"
 7)
 8
 9func (c *Client) urlToBuffer(url string) (*VideoBuffer, int) {
10	if url == "" {
11		return nil, http.StatusBadRequest
12	}
13
14	req, err := http.NewRequest(http.MethodGet, url, nil)
15	if err != nil {
16		logger.Error(err) // bad request
17		return nil, http.StatusInternalServerError
18	}
19
20	resp, err := c.http.Do(req)
21	if err != nil {
22		logger.Error(err) // request failed
23		return nil, http.StatusGone
24	}
25
26	if resp.StatusCode != http.StatusOK {
27		return nil, resp.StatusCode
28	}
29
30	if resp.ContentLength == 0 {
31		return nil, http.StatusNoContent
32	}
33
34	if resp.ContentLength > c.Options.MaxSizeBytes {
35		logger.Debug("Content-Length exceeds max size.")
36		return nil, http.StatusBadRequest
37	}
38	defer resp.Body.Close()
39
40	b := new(bytes.Buffer)
41	l, _ := io.Copy(b, resp.Body)
42	if l != resp.ContentLength {
43		logger.Debug("Content-Length is inconsistent.")
44		return nil, http.StatusBadRequest
45	}
46
47	return &VideoBuffer{b, l}, http.StatusOK
48}
49
50func (c *Client) findCompatibleFormat(video *Video) (*VideoBuffer, int) {
51	for i := len(video.Formats) - 1; i >= 0; i-- {
52		url := video.Formats[i].Url
53		logger.Debug(url)
54		vb, httpStatus := c.urlToBuffer(url)
55		if httpStatus == http.StatusOK {
56			videoBuffer := vb.Clone()
57			c.buffers.Set(video.VideoId, videoBuffer)
58			return vb, i
59		}
60		logger.Debug("Format ", i, "failed with status code ", httpStatus)
61	}
62	return nil, -1
63}
64
65func (c *Client) getBuffer(video Video) (*VideoBuffer, int) {
66	vb, err := c.buffers.Get(video.VideoId)
67	if err != nil {
68		// no cache entry
69		vb, s := c.urlToBuffer(video.Url)
70		if vb != nil {
71			if s == http.StatusOK && vb.Length > 0 {
72				c.buffers.Set(video.VideoId, vb.Clone())
73				return vb, s
74			}
75		}
76		return nil, s
77	}
78	//cache entry
79	videoBuffer := vb.Clone()
80	return videoBuffer, http.StatusOK
81}
82
83func (c *Client) ProxyVideoId(videoId string) (*VideoBuffer, int) {
84	video, err := GetVideoDB(videoId)
85	if err != nil {
86		logger.Info("Cannot proxy a video that is not cached: https://youtu.be/", videoId)
87		return nil, http.StatusBadRequest
88	}
89	return c.getBuffer(*video)
90}