diff options
Diffstat (limited to 'internal/api')
-rw-r--r-- | internal/api/client/media/mediacreate_test.go | 4 | ||||
-rw-r--r-- | internal/api/client/media/mediaupdate_test.go | 2 | ||||
-rw-r--r-- | internal/api/fileserver/servefile.go | 35 | ||||
-rw-r--r-- | internal/api/model/attachment.go | 30 | ||||
-rw-r--r-- | internal/api/model/content.go | 3 |
5 files changed, 38 insertions, 36 deletions
diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go index 6ac63a356..320636721 100644 --- a/internal/api/client/media/mediacreate_test.go +++ b/internal/api/client/media/mediacreate_test.go @@ -201,7 +201,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessful() { Size: "512x288", Aspect: 1.7777778, }, - Focus: apimodel.MediaFocus{ + Focus: &apimodel.MediaFocus{ X: -0.5, Y: 0.5, }, @@ -290,7 +290,7 @@ func (suite *MediaCreateTestSuite) TestMediaCreateSuccessfulV2() { Size: "512x288", Aspect: 1.7777778, }, - Focus: apimodel.MediaFocus{ + Focus: &apimodel.MediaFocus{ X: -0.5, Y: 0.5, }, diff --git a/internal/api/client/media/mediaupdate_test.go b/internal/api/client/media/mediaupdate_test.go index 3b1d94368..1425d80ef 100644 --- a/internal/api/client/media/mediaupdate_test.go +++ b/internal/api/client/media/mediaupdate_test.go @@ -172,7 +172,7 @@ func (suite *MediaUpdateTestSuite) TestUpdateImage() { suite.EqualValues(apimodel.MediaMeta{ Original: apimodel.MediaDimensions{Width: 800, Height: 450, FrameRate: "", Duration: 0, Bitrate: 0, Size: "800x450", Aspect: 1.7777778}, Small: apimodel.MediaDimensions{Width: 256, Height: 144, FrameRate: "", Duration: 0, Bitrate: 0, Size: "256x144", Aspect: 1.7777778}, - Focus: apimodel.MediaFocus{X: -0.1, Y: 0.3}, + Focus: &apimodel.MediaFocus{X: -0.1, Y: 0.3}, }, attachmentReply.Meta) suite.Equal(toUpdate.Blurhash, attachmentReply.Blurhash) suite.Equal(toUpdate.ID, attachmentReply.ID) diff --git a/internal/api/fileserver/servefile.go b/internal/api/fileserver/servefile.go index 2b47db6f2..592d83672 100644 --- a/internal/api/fileserver/servefile.go +++ b/internal/api/fileserver/servefile.go @@ -29,6 +29,7 @@ import ( apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" "github.com/superseriousbusiness/gotosocial/internal/gtserror" + "github.com/superseriousbusiness/gotosocial/internal/iotools" "github.com/superseriousbusiness/gotosocial/internal/log" "github.com/superseriousbusiness/gotosocial/internal/oauth" ) @@ -128,8 +129,34 @@ func (m *Module) ServeFile(c *gin.Context) { return } - // we're good, return the slurped bytes + the rest of the content - c.DataFromReader(http.StatusOK, content.ContentLength, format, io.MultiReader( - bytes.NewReader(b), content.Content, - ), nil) + // reconstruct the original content reader + r := io.MultiReader(bytes.NewReader(b), content.Content) + + // Check the Range header: if this is a simple query for the whole file, we can return it now. + if c.GetHeader("Range") == "" && c.GetHeader("If-Range") == "" { + c.DataFromReader(http.StatusOK, content.ContentLength, format, r, nil) + return + } + + // Range is set, so we need a ReadSeeker to pass to the ServeContent function. + tfs, err := iotools.TempFileSeeker(r) + if err != nil { + err = fmt.Errorf("ServeFile: error creating temp file seeker: %w", err) + apiutil.ErrorHandler(c, gtserror.NewErrorInternalError(err), m.processor.InstanceGet) + return + } + defer func() { + if err := tfs.Close(); err != nil { + log.Errorf("ServeFile: error closing temp file seeker: %s", err) + } + }() + + // to avoid ServeContent wasting time seeking for the + // mime type, set this header already since we know it + c.Header("Content-Type", format) + + // allow ServeContent to handle the rest of the request; + // it will handle Range as appropriate, and write correct + // response headers, http code, etc + http.ServeContent(c.Writer, c.Request, fileName, content.ContentUpdated, tfs) } diff --git a/internal/api/model/attachment.go b/internal/api/model/attachment.go index 244f3cd8d..79de44540 100644 --- a/internal/api/model/attachment.go +++ b/internal/api/model/attachment.go @@ -98,40 +98,12 @@ type Attachment struct { // // swagger:model mediaMeta type MediaMeta struct { - Length string `json:"length,omitempty"` - // Duration of the media in seconds. - // Only set for video and audio. - // example: 5.43 - Duration float32 `json:"duration,omitempty"` - // Framerate of the media. - // Only set for video and gifs. - // example: 30 - FPS uint16 `json:"fps,omitempty"` - // Size of the media, in the format `[width]x[height]`. - // Not set for audio. - // example: 1920x1080 - Size string `json:"size,omitempty"` - // Width of the media in pixels. - // Not set for audio. - // example: 1920 - Width int `json:"width,omitempty"` - // Height of the media in pixels. - // Not set for audio. - // example: 1080 - Height int `json:"height,omitempty"` - // Aspect ratio of the media. - // Equal to width / height. - // example: 1.777777778 - Aspect float32 `json:"aspect,omitempty"` - AudioEncode string `json:"audio_encode,omitempty"` - AudioBitrate string `json:"audio_bitrate,omitempty"` - AudioChannels string `json:"audio_channels,omitempty"` // Dimensions of the original media. Original MediaDimensions `json:"original"` // Dimensions of the thumbnail/small version of the media. Small MediaDimensions `json:"small,omitempty"` // Focus data for the media. - Focus MediaFocus `json:"focus,omitempty"` + Focus *MediaFocus `json:"focus,omitempty"` } // MediaFocus models the focal point of a piece of media. diff --git a/internal/api/model/content.go b/internal/api/model/content.go index 94b32d112..4c0151c2c 100644 --- a/internal/api/model/content.go +++ b/internal/api/model/content.go @@ -21,6 +21,7 @@ package model import ( "io" "net/url" + "time" ) // Content wraps everything needed to serve a blob of content (some kind of media) through the API. @@ -29,6 +30,8 @@ type Content struct { ContentType string // ContentLength in bytes ContentLength int64 + // Time when the content was last updated. + ContentUpdated time.Time // Actual content Content io.ReadCloser // Resource URL to forward to if the file can be fetched from the storage directly (e.g signed S3 URL) |