diff --git a/app/app.go b/app/app.go index bc2802d..4e0657c 100644 --- a/app/app.go +++ b/app/app.go @@ -210,8 +210,7 @@ func (a *App) uploadHandler(w http.ResponseWriter, r *http.Request) { ctx := &struct{}{} a.render("upload", w, ctx) } else if r.Method == "POST" { - // TODO: Move to a constant - r.ParseMultipartForm((10 << 20) * 10) // 100MB + r.ParseMultipartForm(a.Config.Server.MaxUploadSize) file, handler, err := r.FormFile("video_file") if err != nil { @@ -414,6 +413,37 @@ func (a *App) importHandler(w http.ResponseWriter, r *http.Request) { } defer os.Remove(uf.Name()) + log.WithField("video_url", videoInfo.VideoURL).Info("requesting video size") + + res, err := http.Head(videoInfo.VideoURL) + if err != nil { + err := fmt.Errorf("error getting size of video %w", err) + log.Error(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + contentLength := utils.SafeParseInt64(res.Header.Get("Content-Length"), -1) + if contentLength == -1 { + err := fmt.Errorf("error calculating size of video") + log.WithField("contentLength", contentLength).Error(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if contentLength > a.Config.Server.MaxUploadSize { + err := fmt.Errorf( + "imported video would exceed maximum upload size of %s", + humanize.Bytes(uint64(a.Config.Server.MaxUploadSize)), + ) + log. + WithField("contentLength", contentLength). + WithField("max_upload_size", a.Config.Server.MaxUploadSize). + Error(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + log.WithField("contentLength", contentLength).Info("downloading video") + if err := utils.Download(videoInfo.VideoURL, uf.Name()); err != nil { err := fmt.Errorf("error downloading video %s: %w", url, err) log.Error(err) diff --git a/app/config.go b/app/config.go index 73871eb..4d72657 100644 --- a/app/config.go +++ b/app/config.go @@ -22,10 +22,11 @@ type PathConfig struct { // ServerConfig settings for App Server. type ServerConfig struct { - Host string `json:"host"` - Port int `json:"port"` - StorePath string `json:"store_path"` - UploadPath string `json:"upload_path"` + Host string `json:"host"` + Port int `json:"port"` + StorePath string `json:"store_path"` + UploadPath string `json:"upload_path"` + MaxUploadSize int64 `json:"max_upload_size"` } // ThumbnailerConfig settings for Transcoder @@ -61,15 +62,16 @@ func DefaultConfig() *Config { }, }, Server: &ServerConfig{ - Host: "127.0.0.1", - Port: 0, - UploadPath: "uploads", + Host: "0.0.0.0", + Port: 8000, + UploadPath: "uploads", + MaxUploadSize: 104857600, }, Thumbnailer: &ThumbnailerConfig{ - Timeout: 30, + Timeout: 60, }, Transcoder: &TranscoderConfig{ - Timeout: 60, + Timeout: 300, }, Feed: &FeedConfig{ ExternalURL: "http://localhost", diff --git a/config.json b/config.json index 9edf9dc..76d608d 100644 --- a/config.json +++ b/config.json @@ -9,7 +9,8 @@ "host": "0.0.0.0", "port": 8000, "store_path": "tube.db", - "upload_path": "uploads" + "upload_path": "uploads", + "max_upload_size": 104857600 }, "thumbnailer": { "timeout": 60 diff --git a/utils/utils.go b/utils/utils.go index 5293b0a..f80834c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -7,9 +7,19 @@ import ( "net/http" "os" "os/exec" + "strconv" "time" ) +// SafeParseInt64 ... +func SafeParseInt64(s string, d int64) int64 { + n, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return d + } + return n +} + func Download(url, filename string) error { res, err := http.Get(url) if err != nil {