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 > 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 vb, s := c.urlToBuffer(video.Url)
69 if vb.Length > 0 {
70 videoBuffer := vb.Clone()
71 c.buffers.Set(video.VideoId, videoBuffer)
72 }
73 return vb, s
74 }
75
76 videoBuffer := vb.Clone()
77 return videoBuffer, http.StatusOK
78}
79
80func (c *Client) ProxyVideoId(videoId string) (*VideoBuffer, int) {
81 video, err := GetVideoDB(videoId)
82 if err != nil {
83 logger.Info("Cannot proxy a video that is not cached: https://youtu.be/", videoId)
84 return nil, http.StatusBadRequest
85 }
86 return c.getBuffer(*video)
87}