invidious/proxy.go (view raw)
1package invidious
2
3import (
4 "bytes"
5 "io"
6 "net/http"
7)
8
9func (c *Client) urlToBuffer(url string) (*bytes.Buffer, int64, int) {
10 if url == "" {
11 return nil, 0, 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, 0, http.StatusInternalServerError
18 }
19
20 resp, err := c.http.Do(req)
21 if err != nil {
22 logger.Error(err) // request failed
23 return nil, 0, http.StatusGone
24 }
25
26 if resp.StatusCode != http.StatusOK {
27 return nil, 0, resp.StatusCode
28 }
29
30 if resp.ContentLength == 0 {
31 return nil, 0, http.StatusNoContent
32 }
33
34 if resp.ContentLength > maxSizeBytes {
35 logger.Debug("Content-Length exceeds max size.")
36 return nil, 0, http.StatusBadRequest
37 }
38 defer resp.Body.Close()
39
40 b := new(bytes.Buffer)
41 l, err := io.Copy(b, resp.Body)
42 if l != resp.ContentLength {
43 logger.Debug("Content-Length is inconsistent.")
44 return nil, 0, http.StatusBadRequest
45 }
46
47 return b, l, http.StatusOK
48}
49
50func (c *Client) findCompatibleFormat(video *Video) (*bytes.Buffer, int64, int) {
51 for i := len(video.Formats) - 1; i >= 0; i-- {
52 url := video.Formats[i].Url
53 logger.Debug(url)
54 b, l, httpStatus := c.urlToBuffer(url)
55 if httpStatus == http.StatusOK {
56 return b, l, i
57 }
58 logger.Debug("Format ", i, "failed with status code ", httpStatus)
59 }
60 return nil, 0, -1
61}
62
63func (c *Client) ProxyVideoId(videoId string) (*bytes.Buffer, int64, int) {
64 video, err := GetVideoDB(videoId)
65 if err != nil {
66 logger.Info("Cannot proxy a video that is not cached: https://youtu.be/", videoId)
67 return nil, 0, http.StatusBadRequest
68 }
69
70 return c.urlToBuffer(video.Url)
71}