-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asynchronous uploads (MSC2246) #364
Changes from all commits
dc1401b
ffdff09
f39ed4a
caefa2a
c8c6ec1
8e27b16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,14 +6,17 @@ import ( | |
"io/ioutil" | ||
"net/http" | ||
"path/filepath" | ||
"time" | ||
|
||
"github.com/gorilla/mux" | ||
"github.com/sirupsen/logrus" | ||
"github.com/turt2live/matrix-media-repo/api" | ||
"github.com/turt2live/matrix-media-repo/common" | ||
"github.com/turt2live/matrix-media-repo/common/rcontext" | ||
"github.com/turt2live/matrix-media-repo/controllers/info_controller" | ||
"github.com/turt2live/matrix-media-repo/controllers/upload_controller" | ||
"github.com/turt2live/matrix-media-repo/quota" | ||
"github.com/turt2live/matrix-media-repo/util" | ||
"github.com/turt2live/matrix-media-repo/util/cleanup" | ||
) | ||
|
||
|
@@ -22,14 +25,52 @@ type MediaUploadedResponse struct { | |
Blurhash string `json:"xyz.amorgan.blurhash,omitempty"` | ||
} | ||
|
||
type MediaCreatedResponse struct { | ||
ContentUri string `json:"content_uri"` | ||
UnusedExpiresAt int64 `json:"unused_expires_at"` | ||
} | ||
|
||
func CreateMedia(r *http.Request, rctx rcontext.RequestContext, user api.UserInfo) interface{} { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't r0, so should be in the |
||
media, _, err := upload_controller.CreateMedia(r.Host, rctx) | ||
if err != nil { | ||
rctx.Log.Error("Unexpected error creating media reference: " + err.Error()) | ||
return api.InternalServerError("Unexpected Error") | ||
} | ||
|
||
if err = upload_controller.PersistMedia(media, user.UserId, rctx); err != nil { | ||
rctx.Log.Error("Unexpected error persisting media reference: " + err.Error()) | ||
return api.InternalServerError("Unexpected Error") | ||
} | ||
|
||
return &MediaCreatedResponse{ | ||
ContentUri: media.MxcUri(), | ||
UnusedExpiresAt: time.Now().Unix() + int64(rctx.Config.Features.MSC2246Async.AsyncUploadExpirySecs), | ||
} | ||
} | ||
|
||
func UploadMedia(r *http.Request, rctx rcontext.RequestContext, user api.UserInfo) interface{} { | ||
var server = "" | ||
var mediaId = "" | ||
|
||
filename := filepath.Base(r.URL.Query().Get("filename")) | ||
defer cleanup.DumpAndCloseStream(r.Body) | ||
|
||
if rctx.Config.Features.MSC2246Async.Enabled { | ||
params := mux.Vars(r) | ||
server = params["server"] | ||
mediaId = params["mediaId"] | ||
} | ||
|
||
rctx = rctx.LogWithFields(logrus.Fields{ | ||
"server": server, | ||
"mediaId": mediaId, | ||
"filename": filename, | ||
}) | ||
|
||
if server != "" && (!util.IsServerOurs(server) || server != r.Host) { | ||
return api.NotFoundError() | ||
} | ||
|
||
contentType := r.Header.Get("Content-Type") | ||
if contentType == "" { | ||
contentType = "application/octet-stream" // binary | ||
|
@@ -59,12 +100,16 @@ func UploadMedia(r *http.Request, rctx rcontext.RequestContext, user api.UserInf | |
|
||
contentLength := upload_controller.EstimateContentLength(r.ContentLength, r.Header.Get("Content-Length")) | ||
|
||
media, err := upload_controller.UploadMedia(r.Body, contentLength, contentType, filename, user.UserId, r.Host, rctx) | ||
media, err := upload_controller.UploadMedia(r.Body, contentLength, contentType, filename, user.UserId, r.Host, mediaId, rctx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if err != nil { | ||
io.Copy(ioutil.Discard, r.Body) // Ditch the entire request | ||
|
||
if err == common.ErrMediaQuarantined { | ||
return api.BadRequest("This file is not permitted on this server") | ||
} else if err == common.ErrCannotOverwriteMedia { | ||
return api.CannotOverwriteMedia() | ||
} else if err == common.ErrMediaNotFound { | ||
return api.NotFoundError() | ||
} | ||
|
||
rctx.Log.Error("Unexpected error storing media: " + err.Error()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally this is a non-pointer
int
throughout, for code clarity more than anything. A wait time of zero is still semantically possible.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having it as a nillable pointer was to make it distinct it's not set vs it being set to zero. Not setting it from the request makes the code pick up the default from the configuration file.