mediaapi/writers/upload: Use Logger and MediaMetadata from uploadRequest

Also make storeFileAndMetadata a method on uploadRequest.
This commit is contained in:
Robert Swain 2017-05-22 17:05:45 +02:00
parent 8626308dac
commit 48c3a505cd

View file

@ -37,10 +37,11 @@ import (
// NOTE: The members come from HTTP request metadata such as headers, query parameters or can be derived from such // NOTE: The members come from HTTP request metadata such as headers, query parameters or can be derived from such
type uploadRequest struct { type uploadRequest struct {
MediaMetadata *types.MediaMetadata MediaMetadata *types.MediaMetadata
Logger *log.Entry
} }
// Validate validates the uploadRequest fields // Validate validates the uploadRequest fields
func (r uploadRequest) Validate(maxFileSizeBytes types.FileSizeBytes) *util.JSONResponse { func (r *uploadRequest) Validate(maxFileSizeBytes types.FileSizeBytes) *util.JSONResponse {
// TODO: Any validation to be done on ContentDisposition? // TODO: Any validation to be done on ContentDisposition?
if r.MediaMetadata.FileSizeBytes < 1 { if r.MediaMetadata.FileSizeBytes < 1 {
@ -118,6 +119,7 @@ func parseAndValidateRequest(req *http.Request, cfg *config.MediaAPI) (*uploadRe
UploadName: types.Filename(req.FormValue("filename")), UploadName: types.Filename(req.FormValue("filename")),
UserID: types.MatrixUserID(userID), UserID: types.MatrixUserID(userID),
}, },
Logger: util.GetLogger(req.Context()),
} }
if resErr = r.Validate(cfg.MaxFileSizeBytes); resErr != nil { if resErr = r.Validate(cfg.MaxFileSizeBytes); resErr != nil {
@ -142,26 +144,26 @@ func parseAndValidateRequest(req *http.Request, cfg *config.MediaAPI) (*uploadRe
// is ready and if we fail to move the file, it never gets added to the database. // is ready and if we fail to move the file, it never gets added to the database.
// In case of any error, appropriate files and directories are cleaned up a // In case of any error, appropriate files and directories are cleaned up a
// util.JSONResponse error is returned. // util.JSONResponse error is returned.
func storeFileAndMetadata(tmpDir types.Path, absBasePath types.Path, mediaMetadata *types.MediaMetadata, db *storage.Database, logger *log.Entry) *util.JSONResponse { func (r *uploadRequest) storeFileAndMetadata(tmpDir types.Path, absBasePath types.Path, db *storage.Database) *util.JSONResponse {
finalPath, duplicate, err := fileutils.MoveFileWithHashCheck(tmpDir, mediaMetadata, absBasePath, logger) finalPath, duplicate, err := fileutils.MoveFileWithHashCheck(tmpDir, r.MediaMetadata, absBasePath, r.Logger)
if err != nil { if err != nil {
logger.WithError(err).Error("Failed to move file.") r.Logger.WithError(err).Error("Failed to move file.")
return &util.JSONResponse{ return &util.JSONResponse{
Code: 400, Code: 400,
JSON: jsonerror.Unknown(fmt.Sprintf("Failed to upload")), JSON: jsonerror.Unknown(fmt.Sprintf("Failed to upload")),
} }
} }
if duplicate { if duplicate {
logger.WithField("dst", finalPath).Info("File was stored previously - discarding duplicate") r.Logger.WithField("dst", finalPath).Info("File was stored previously - discarding duplicate")
} }
if err = db.StoreMediaMetadata(mediaMetadata); err != nil { if err = db.StoreMediaMetadata(r.MediaMetadata); err != nil {
logger.WithError(err).Warn("Failed to store metadata") r.Logger.WithError(err).Warn("Failed to store metadata")
// If the file is a duplicate (has the same hash as an existing file) then // If the file is a duplicate (has the same hash as an existing file) then
// there is valid metadata in the database for that file. As such we only // there is valid metadata in the database for that file. As such we only
// remove the file if it is not a duplicate. // remove the file if it is not a duplicate.
if duplicate == false { if duplicate == false {
fileutils.RemoveDir(types.Path(path.Dir(finalPath)), logger) fileutils.RemoveDir(types.Path(path.Dir(finalPath)), r.Logger)
} }
return &util.JSONResponse{ return &util.JSONResponse{
Code: 400, Code: 400,
@ -179,14 +181,12 @@ func storeFileAndMetadata(tmpDir types.Path, absBasePath types.Path, mediaMetada
// Uploaded files are processed piece-wise to avoid DoS attacks which would starve the server of memory. // Uploaded files are processed piece-wise to avoid DoS attacks which would starve the server of memory.
// TODO: We should time out requests if they have not received any data within a configured timeout period. // TODO: We should time out requests if they have not received any data within a configured timeout period.
func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.JSONResponse { func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.JSONResponse {
logger := util.GetLogger(req.Context())
r, resErr := parseAndValidateRequest(req, cfg) r, resErr := parseAndValidateRequest(req, cfg)
if resErr != nil { if resErr != nil {
return *resErr return *resErr
} }
logger.WithFields(log.Fields{ r.Logger.WithFields(log.Fields{
"Origin": r.MediaMetadata.Origin, "Origin": r.MediaMetadata.Origin,
"UploadName": r.MediaMetadata.UploadName, "UploadName": r.MediaMetadata.UploadName,
"FileSizeBytes": r.MediaMetadata.FileSizeBytes, "FileSizeBytes": r.MediaMetadata.FileSizeBytes,
@ -208,8 +208,8 @@ func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.
if copyError == fileutils.ErrFileIsTooLarge { if copyError == fileutils.ErrFileIsTooLarge {
logFields["MaxFileSizeBytes"] = cfg.MaxFileSizeBytes logFields["MaxFileSizeBytes"] = cfg.MaxFileSizeBytes
} }
logger.WithError(copyError).WithFields(logFields).Warn("Error while transferring file") r.Logger.WithError(copyError).WithFields(logFields).Warn("Error while transferring file")
fileutils.RemoveDir(tmpDir, logger) fileutils.RemoveDir(tmpDir, r.Logger)
return util.JSONResponse{ return util.JSONResponse{
Code: 400, Code: 400,
JSON: jsonerror.Unknown(fmt.Sprintf("Failed to upload")), JSON: jsonerror.Unknown(fmt.Sprintf("Failed to upload")),
@ -220,7 +220,7 @@ func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.
r.MediaMetadata.Base64Hash = hash r.MediaMetadata.Base64Hash = hash
r.MediaMetadata.MediaID = types.MediaID(hash) r.MediaMetadata.MediaID = types.MediaID(hash)
logger.WithFields(log.Fields{ r.Logger.WithFields(log.Fields{
"MediaID": r.MediaMetadata.MediaID, "MediaID": r.MediaMetadata.MediaID,
"Origin": r.MediaMetadata.Origin, "Origin": r.MediaMetadata.Origin,
"Base64Hash": r.MediaMetadata.Base64Hash, "Base64Hash": r.MediaMetadata.Base64Hash,
@ -234,7 +234,7 @@ func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.
mediaMetadata, err := db.GetMediaMetadata(r.MediaMetadata.MediaID, r.MediaMetadata.Origin) mediaMetadata, err := db.GetMediaMetadata(r.MediaMetadata.MediaID, r.MediaMetadata.Origin)
if err == nil { if err == nil {
r.MediaMetadata = mediaMetadata r.MediaMetadata = mediaMetadata
fileutils.RemoveDir(tmpDir, logger) fileutils.RemoveDir(tmpDir, r.Logger)
return util.JSONResponse{ return util.JSONResponse{
Code: 200, Code: 200,
JSON: uploadResponse{ JSON: uploadResponse{
@ -242,12 +242,12 @@ func Upload(req *http.Request, cfg *config.MediaAPI, db *storage.Database) util.
}, },
} }
} else if err != sql.ErrNoRows { } else if err != sql.ErrNoRows {
logger.WithError(err).WithField("MediaID", r.MediaMetadata.MediaID).Warn("Failed to query database") r.Logger.WithError(err).WithField("MediaID", r.MediaMetadata.MediaID).Warn("Failed to query database")
} }
// TODO: generate thumbnails // TODO: generate thumbnails
resErr = storeFileAndMetadata(tmpDir, cfg.AbsBasePath, r.MediaMetadata, db, logger) resErr = r.storeFileAndMetadata(tmpDir, cfg.AbsBasePath, db)
if resErr != nil { if resErr != nil {
return *resErr return *resErr
} }