diff --git a/changelogs/client_server/newsfragments/1858.deprecation b/changelogs/client_server/newsfragments/1858.deprecation new file mode 100644 index 000000000..6e93dca58 --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.deprecation @@ -0,0 +1 @@ +Use of the `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead. \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.feature.1 b/changelogs/client_server/newsfragments/1858.feature.1 new file mode 100644 index 000000000..02b9b51ed --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.feature.1 @@ -0,0 +1 @@ +Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.feature.2 b/changelogs/client_server/newsfragments/1858.feature.2 new file mode 100644 index 000000000..63dfbb787 --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.feature.2 @@ -0,0 +1 @@ +Some media endpoints are now consistently under `/_matrix/client/{version}/media/*` instead of `/_matrix/media/*`, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.new.1 b/changelogs/client_server/newsfragments/1858.new.1 new file mode 100644 index 000000000..9d02447f7 --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.new.1 @@ -0,0 +1 @@ +[`GET /_matrix/client/v1/media/config`](/client-server-api/#get_matrixclientv1mediaconfig) \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.new.2 b/changelogs/client_server/newsfragments/1858.new.2 new file mode 100644 index 000000000..07e7763ae --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.new.2 @@ -0,0 +1 @@ +[`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid) \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.new.3 b/changelogs/client_server/newsfragments/1858.new.3 new file mode 100644 index 000000000..49b67f049 --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.new.3 @@ -0,0 +1 @@ +[`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}/{fileName}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaidfilename) \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.new.4 b/changelogs/client_server/newsfragments/1858.new.4 new file mode 100644 index 000000000..dda53b330 --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.new.4 @@ -0,0 +1 @@ +[`GET /_matrix/client/v1/media/preview_url`](/client-server-api/#get_matrixclientv1mediapreview_url) \ No newline at end of file diff --git a/changelogs/client_server/newsfragments/1858.new.5 b/changelogs/client_server/newsfragments/1858.new.5 new file mode 100644 index 000000000..021b4023d --- /dev/null +++ b/changelogs/client_server/newsfragments/1858.new.5 @@ -0,0 +1 @@ +[`GET /_matrix/client/v1/media/thumbnail/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid) \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1858.deprecation b/changelogs/server_server/newsfragments/1858.deprecation new file mode 100644 index 000000000..fd3d25765 --- /dev/null +++ b/changelogs/server_server/newsfragments/1858.deprecation @@ -0,0 +1 @@ +Use of the Client-Server API `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead. \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1858.feature b/changelogs/server_server/newsfragments/1858.feature new file mode 100644 index 000000000..02b9b51ed --- /dev/null +++ b/changelogs/server_server/newsfragments/1858.feature @@ -0,0 +1 @@ +Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916). \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1858.new.1 b/changelogs/server_server/newsfragments/1858.new.1 new file mode 100644 index 000000000..e50d5fd18 --- /dev/null +++ b/changelogs/server_server/newsfragments/1858.new.1 @@ -0,0 +1 @@ +[`GET /_matrix/federation/v1/media/download/{mediaId}`](/server-server-api/#get_matrixfederationv1mediadownloadmediaid) \ No newline at end of file diff --git a/changelogs/server_server/newsfragments/1858.new.2 b/changelogs/server_server/newsfragments/1858.new.2 new file mode 100644 index 000000000..1da2a693f --- /dev/null +++ b/changelogs/server_server/newsfragments/1858.new.2 @@ -0,0 +1 @@ +[`GET /_matrix/federation/v1/media/thumbnail/{mediaId}`](/server-server-api/#get_matrixfederationv1mediathumbnailmediaid) \ No newline at end of file diff --git a/content/client-server-api/_index.md b/content/client-server-api/_index.md index 126a51039..ebf1895bd 100644 --- a/content/client-server-api/_index.md +++ b/content/client-server-api/_index.md @@ -37,9 +37,8 @@ The exceptions are: which take an empty request body. Similarly, all endpoints require the server to return a JSON object, -with the exception of 200 responses to -[`GET /_matrix/media/v3/download/{serverName}/{mediaId}`](#get_matrixmediav3downloadservernamemediaid) -and [`GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}`](#get_matrixmediav3thumbnailservernamemediaid). +with the exception of 200 responses to the media download endpoints in the +[Content Repository module](#content-repository). Servers must include a `Content-Type` header of `application/json` for all JSON responses. All JSON data, in requests or responses, must be encoded using UTF-8. diff --git a/content/client-server-api/modules/content_repo.md b/content/client-server-api/modules/content_repo.md index cef70b3dc..a01381561 100644 --- a/content/client-server-api/modules/content_repo.md +++ b/content/client-server-api/modules/content_repo.md @@ -23,19 +23,67 @@ When serving content, the server SHOULD provide a interacting with the media repository. {{% /boxes/added-in-paragraph %}} +{{% boxes/added-in-paragraph %}} +{{< changed-in v="1.11" >}} The unauthenticated download endpoints have been +deprecated in favour of newer, authenticated, ones. This change includes updating +the paths of all media endpoints from `/_matrix/media/*` to `/_matrix/client/{version}/media/*`, +with the exception of the `/upload` and `/create` endpoints. The upload/create +endpoints are expected to undergo a similar transition in a later version of the +specification. +{{% /boxes/added-in-paragraph %}} + #### Matrix Content (`mxc://`) URIs Content locations are represented as Matrix Content (`mxc://`) URIs. They look like: - mxc:/// +``` +mxc:/// + + : The name of the homeserver where this content originated, e.g. matrix.org + : An opaque ID which identifies the content. +``` + +#### Client behaviour {id="content-repo-client-behaviour"} + +Clients can access the content repository using the following endpoints. + +{{% boxes/added-in-paragraph %}} +{{< changed-in v="1.11" >}} Clients SHOULD NOT use the deprecated media endpoints +described below. Instead, they SHOULD use the new endpoints which require authentication. +{{% /boxes/added-in-paragraph %}} + +{{% boxes/warning %}} +By Matrix 1.12, servers SHOULD "freeze" the deprecated, unauthenticated, endpoints +to prevent newly-uploaded media from being downloaded. This SHOULD mean that any +media uploaded *before* the freeze remains accessible via the deprecated endpoints, +and any media uploaded *after* (or *during*) the freeze SHOULD only be accessible +through the new, authenticated, endpoints. For remote media, "newly-uploaded" is +determined by the date the cache was populated. This may mean the media is older +than the freeze, but because the server had to re-download it, it is now considered +"new". + +Clients SHOULD update to support the authenticated endpoints before servers freeze +unauthenticated access. + +Servers SHOULD consider their local ecosystem impact before enacting a freeze. +This could mean ensuring their users' typical clients support the new endpoints +when available, or updating bridges to start using media proxies. + +In addition to the above, servers SHOULD exclude [IdP icons used in the `m.login.sso` flow](/client-server-api/#definition-mloginsso-flow-schema) +from the freeze. See the `m.login.sso` flow schema for details. + +An *example* timeline for a server may be: - : The name of the homeserver where this content originated, e.g. matrix.org - : An opaque ID which identifies the content. +* Matrix 1.11 release: Clients begin supporting authenticated media. +* Matrix 1.12 release: Servers freeze unauthenticated media access. + * Media uploaded prior to this point still works with the deprecated endpoints. + * Newly uploaded (or cached) media *only* works on the authenticated endpoints. -#### Client behaviour +Matrix 1.12 is expected to be released in the July-September 2024 calendar quarter. +{{% /boxes/warning %}} -Clients can upload and download content using the following HTTP APIs. +{{% http-api spec="client-server" api="authed-content-repo" %}} {{% http-api spec="client-server" api="content-repo" %}} diff --git a/content/server-server-api.md b/content/server-server-api.md index 365613dfd..9e92bfd91 100644 --- a/content/server-server-api.md +++ b/content/server-server-api.md @@ -1196,15 +1196,26 @@ using the following EDU: Attachments to events (images, files, etc) are uploaded to a homeserver via the Content Repository described in the [Client-Server -API](/client-server-api). When a server wishes +API](/client-server-api/#content-repository). When a server wishes to serve content originating from a remote server, it needs to ask the remote server for the media. -Servers should use the server described in the Matrix Content URI, which -has the format `mxc://{ServerName}/{MediaID}`. Servers should use the -download endpoint described in the [Client-Server -API](/client-server-api), being sure to use -the `allow_remote` parameter (set to `false`). +Servers MUST use the server described in the [Matrix Content URI](/client-server-api/#matrix-content-mxc-uris). +Formatted as `mxc://{ServerName}/{MediaID}`, servers MUST download the media from +`ServerName` using the below endpoints. + +{{% boxes/added-in-paragraph %}} +{{< changed-in v="1.11" >}} Servers were previously advised to use the `/_matrix/media/*` +endpoints described by the [Content Repository module in the Client-Server API](/client-server-api/#content-repository), +however, those endpoints have been deprecated. New endpoints are introduced which +require authentication. Naturally, as a server is not a user, they cannot provide +the required access token to those endpoints. Instead, servers MUST try the endpoints +described below before falling back to the deprecated `/_matrix/media/*` endpoints +when they receive a `404 M_UNRECOGNIZED` error. When falling back, servers MUST +be sure to set `allow_remote` to `false`. +{{% /boxes/added-in-paragraph %}} + +{{% http-api spec="server-server" api="content_repository" %}} ## Server Access Control Lists (ACLs) diff --git a/data/api/client-server/authed-content-repo.yaml b/data/api/client-server/authed-content-repo.yaml new file mode 100644 index 000000000..9741d6183 --- /dev/null +++ b/data/api/client-server/authed-content-repo.yaml @@ -0,0 +1,518 @@ +# Copyright 2016 OpenMarket Ltd +# Copyright 2019-2024 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Client-Server (Authenticated) Content Repository API + version: 1.0.0 +paths: + "/media/download/{serverName}/{mediaId}": + get: + x-addedInMatrixVersion: "1.11" + summary: Download content from the content repository. + description: |- + {{% boxes/note %}} + Clients SHOULD NOT generate or use URLs which supply the access token in + the query string. These URLs may be copied by users verbatim and provided + in a chat message to another user, disclosing the sender's access token. + {{% /boxes/note %}} + + Clients MAY be redirected using the 307/308 responses below to download + the request object. This is typical when the homeserver uses a Content + Delivery Network (CDN). + operationId: getContentAuthed + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + parameters: + - $ref: '#/components/parameters/serverName' + - $ref: '#/components/parameters/mediaId' + - $ref: '#/components/parameters/timeout_ms' + responses: + "200": + description: The content that was previously uploaded. + headers: + Content-Type: + $ref: '#/components/headers/downloadContentType' + Content-Disposition: + description: The name of the file that was previously uploaded, if set. + schema: + type: string + content: + application/octet-stream: + schema: + # This is a workaround for us not being able to say the response is required. + description: "**Required.** The bytes for the uploaded file." + "307": + $ref: '#/components/responses/downloadRedirect' + "308": + $ref: '#/components/responses/downloadRedirect' + "429": + $ref: '#/components/responses/rateLimited' + "502": + $ref: '#/components/responses/downloadTooLarge' + "504": + $ref: '#/components/responses/notYetUploaded' + tags: + - Media + "/media/download/{serverName}/{mediaId}/{fileName}": + get: + x-addedInMatrixVersion: "1.11" + summary: Download content from the content repository overriding the file name. + description: |- + This will download content from the content repository (same as + the previous endpoint) but replaces the target file name with the one + provided by the caller. + + {{% boxes/note %}} + Clients SHOULD NOT generate or use URLs which supply the access token in + the query string. These URLs may be copied by users verbatim and provided + in a chat message to another user, disclosing the sender's access token. + {{% /boxes/note %}} + + Clients MAY be redirected using the 307/308 responses below to download + the request object. This is typical when the homeserver uses a Content + Delivery Network (CDN). + operationId: getContentOverrideNameAuthed + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + parameters: + - $ref: '#/components/parameters/serverName' + - $ref: '#/components/parameters/mediaId' + - in: path + name: fileName + required: true + description: A filename to give in the `Content-Disposition` header. + example: filename.jpg + schema: + type: string + - $ref: '#/components/parameters/timeout_ms' + responses: + "200": + description: The content that was previously uploaded. + headers: + Content-Type: + $ref: '#/components/headers/downloadContentType' + Content-Disposition: + description: |- + The `fileName` requested or the name of the file that was previously + uploaded, if set. + schema: + type: string + content: + application/octet-stream: + schema: + # This is a workaround for us not being able to say the response is required. + description: "**Required.** The bytes for the uploaded file." + "307": + $ref: '#/components/responses/downloadRedirect' + "308": + $ref: '#/components/responses/downloadRedirect' + "429": + $ref: '#/components/responses/rateLimited' + "502": + $ref: '#/components/responses/downloadTooLarge' + "504": + $ref: '#/components/responses/notYetUploaded' + tags: + - Media + "/media/thumbnail/{serverName}/{mediaId}": + get: + x-addedInMatrixVersion: "1.11" + summary: Download a thumbnail of content from the content repository + description: |- + Download a thumbnail of content from the content repository. + See the [Thumbnails](/client-server-api/#thumbnails) section for more information. + + {{% boxes/note %}} + Clients SHOULD NOT generate or use URLs which supply the access token in + the query string. These URLs may be copied by users verbatim and provided + in a chat message to another user, disclosing the sender's access token. + {{% /boxes/note %}} + + Clients MAY be redirected using the 307/308 responses below to download + the request object. This is typical when the homeserver uses a Content + Delivery Network (CDN). + operationId: getContentThumbnailAuthed + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + parameters: + - $ref: '#/components/parameters/serverName' + - $ref: '#/components/parameters/mediaId' + - in: query + name: width + required: true + description: |- + The *desired* width of the thumbnail. The actual thumbnail may be + larger than the size specified. + example: 64 + schema: + type: integer + - in: query + name: height + required: true + description: |- + The *desired* height of the thumbnail. The actual thumbnail may be + larger than the size specified. + example: 64 + schema: + type: integer + - in: query + name: method + description: |- + The desired resizing method. See the [Thumbnails](/client-server-api/#thumbnails) + section for more information. + example: scale + schema: + type: string + enum: + - crop + - scale + - $ref: '#/components/parameters/timeout_ms' + - in: query + name: animated + x-addedInMatrixVersion: "1.11" + required: false + description: | + Indicates preference for an animated thumbnail from the server, if possible. Animated + thumbnails typically use the content types `image/gif`, `image/png` (with APNG format), + `image/apng`, and `image/webp` instead of the common static `image/png` or `image/jpeg` + content types. + + When `true`, the server SHOULD return an animated thumbnail if possible and supported. + When `false`, the server MUST NOT return an animated thumbnail. For example, returning a + static `image/png` or `image/jpeg` thumbnail. When not provided, the server SHOULD NOT + return an animated thumbnail. + + Servers SHOULD prefer to return `image/webp` thumbnails when supporting animation. + + When `true` and the media cannot be animated, such as in the case of a JPEG or PDF, the + server should behave as though `animated` is `false`. + example: false + schema: + type: boolean + responses: + "200": + description: A thumbnail of the requested content. + headers: + Content-Type: + description: The content type of the thumbnail. + schema: + type: string + enum: + - image/jpeg + - image/png + - image/apng + - image/gif + - image/webp + content: + image/jpeg: + schema: + # This is a workaround for us not being able to say the response is required. + description: "**Required.** The bytes for the thumbnail." + image/png: + schema: + x-changedInMatrixVersion: + "1.11": The PNG may be of the APNG variety if animation is supported and requested. + description: | + **Required.** The bytes for the thumbnail. The thumbnail MAY use an animated + format if `animated=true`. + image/apng: + schema: + x-addedInMatrixVersion: "1.11" + description: "**Required.** The bytes for the *animated* thumbnail." + image/gif: + schema: + x-addedInMatrixVersion: "1.11" + description: "**Required.** The bytes for the *animated* thumbnail." + image/webp: + schema: + x-addedInMatrixVersion: "1.11" + description: "**Required.** The bytes for the *animated* thumbnail." + "307": + $ref: '#/components/responses/thumbnailRedirect' + "308": + $ref: '#/components/responses/thumbnailRedirect' + "400": + description: |- + The request does not make sense to the server, or the server cannot thumbnail + the content. For example, the client requested non-integer dimensions or asked + for negatively-sized images. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_UNKNOWN", + "error": "Cannot generate thumbnails for the requested content" + } + "413": + description: The local content is too large for the server to thumbnail. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to thumbnail" + } + "429": + $ref: '#/components/responses/rateLimited' + "502": + description: The remote content is too large for the server to thumbnail. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to thumbnail" + } + "504": + $ref: '#/components/responses/notYetUploaded' + tags: + - Media + /media/preview_url: + get: + x-addedInMatrixVersion: "1.11" + summary: Get information about a URL for a client + description: |- + Get information about a URL for the client. Typically this is called when a + client sees a URL in a message and wants to render a preview for the user. + + {{% boxes/note %}} + Clients should consider avoiding this endpoint for URLs posted in encrypted + rooms. Encrypted rooms often contain more sensitive information the users + do not want to share with the homeserver, and this can mean that the URLs + being shared should also not be shared with the homeserver. + {{% /boxes/note %}} + operationId: getUrlPreviewAuthed + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + parameters: + - in: query + name: url + description: The URL to get a preview of. + required: true + example: https://matrix.org + schema: + type: string + format: uri + - in: query + name: ts + description: |- + The preferred point in time to return a preview for. The server may + return a newer version if it does not have the requested version + available. + example: 1510610716656 + schema: + type: integer + format: int64 + responses: + "200": + description: |- + The OpenGraph data for the URL, which may be empty. Some values are + replaced with matrix equivalents if they are provided in the response. + The differences from the OpenGraph protocol are described here. + content: + application/json: + schema: + type: object + properties: + matrix:image:size: + type: integer + format: int64 + description: The byte-size of the image. Omitted if there is no image attached. + og:image: + type: string + format: uri + description: An [`mxc://` URI](/client-server-api/#matrix-content-mxc-uris) to + the image. Omitted if there is no image. + examples: + response: + value: { + "og:title": "Matrix Blog Post", + "og:description": "This is a really cool blog post from matrix.org", + "og:image": "mxc://example.com/ascERGshawAWawugaAcauga", + "og:image:type": "image/png", + "og:image:height": 48, + "og:image:width": 48, + "matrix:image:size": 102400 + } + "429": + $ref: '#/components/responses/rateLimited' + tags: + - Media + /media/config: + get: + x-addedInMatrixVersion: "1.11" + summary: Get the configuration for the content repository. + description: |- + This endpoint allows clients to retrieve the configuration of the content + repository, such as upload limitations. + Clients SHOULD use this as a guide when using content repository endpoints. + All values are intentionally left optional. Clients SHOULD follow + the advice given in the field description when the field is not available. + + {{% boxes/note %}} + Both clients and server administrators should be aware that proxies + between the client and the server may affect the apparent behaviour of content + repository APIs, for example, proxies may enforce a lower upload size limit + than is advertised by the server on this endpoint. + {{% /boxes/note %}} + operationId: getConfigAuthed + security: + - accessTokenQuery: [] + - accessTokenBearer: [] + responses: + "200": + description: The public content repository configuration for the matrix server. + content: + application/json: + schema: + type: object + properties: + m.upload.size: + type: integer + format: int64 + description: |- + The maximum size an upload can be in bytes. + Clients SHOULD use this as a guide when uploading content. + If not listed or null, the size limit should be treated as unknown. + examples: + response: + value: { + "m.upload.size": 50000000 + } + "429": + $ref: '#/components/responses/rateLimited' + tags: + - Media +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8008 + basePath: + default: /_matrix/client/v1 +components: + securitySchemes: + accessTokenQuery: + $ref: definitions/security.yaml#/accessTokenQuery + accessTokenBearer: + $ref: definitions/security.yaml#/accessTokenBearer + parameters: + serverName: + in: path + name: serverName + required: true + description: | + The server name from the `mxc://` URI (the authority component). + example: matrix.org + schema: + type: string + format: mx-server-name + mediaId: + in: path + name: mediaId + required: true + description: | + The media ID from the `mxc://` URI (the path component). + example: ascERGshawAWawugaAcauga + schema: + type: string + timeout_ms: + in: query + name: timeout_ms + x-addedInMatrixVersion: "1.7" + description: | + The maximum number of milliseconds that the client is willing to wait to + start receiving data, in the case that the content has not yet been + uploaded. The default value is 20000 (20 seconds). The content + repository can and should impose a maximum value for this parameter. The + content repository may also choose to respond before the timeout. + example: 5000 + schema: + type: integer + format: int64 + default: 20000 + responses: + rateLimited: + description: This request was rate-limited. + content: + application/json: + schema: + $ref: definitions/errors/rate_limited.yaml + notYetUploaded: + description: |- + The content is not yet available. A [standard error response](/client-server-api/#standard-error-response) + will be returned with the `errcode` `M_NOT_YET_UPLOADED`. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_NOT_YET_UPLOADED", + "error": "Content has not yet been uploaded" + } + downloadRedirect: + description: A redirect to the requested content. + headers: + Location: + description: The URL of the content. + schema: + type: string + format: uri + downloadTooLarge: + description: The content is too large for the server to serve. + content: + application/json: + schema: + $ref: definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to serve" + } + thumbnailRedirect: + description: A redirect to the thumbnail of the requested content. + headers: + Location: + description: The URL of the thumbnail content. + schema: + type: string + format: uri + headers: + downloadContentType: + description: The content type of the file that was previously uploaded. + schema: + type: string + diff --git a/data/api/client-server/content-repo.yaml b/data/api/client-server/content-repo.yaml index e6d55b51a..1dac8b10d 100644 --- a/data/api/client-server/content-repo.yaml +++ b/data/api/client-server/content-repo.yaml @@ -217,7 +217,20 @@ paths: - Media "/media/v3/download/{serverName}/{mediaId}": get: + deprecated: true summary: Download content from the content repository. + description: |- + {{% boxes/note %}} + Replaced by [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid) + (requires authentication). + {{% /boxes/note %}} + + {{% boxes/warning %}} + {{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND` + for media which exists, but is after the server froze unauthenticated + media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more + information. + {{% /boxes/warning %}} operationId: getContent parameters: - $ref: '#/components/parameters/serverName' @@ -254,11 +267,24 @@ paths: - Media "/media/v3/download/{serverName}/{mediaId}/{fileName}": get: + deprecated: true summary: Download content from the content repository overriding the file name description: |- + {{% boxes/note %}} + Replaced by [`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}/{fileName}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaidfilename) + (requires authentication). + {{% /boxes/note %}} + This will download content from the content repository (same as the previous endpoint) but replace the target file name with the one provided by the caller. + + {{% boxes/warning %}} + {{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND` + for media which exists, but is after the server froze unauthenticated + media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more + information. + {{% /boxes/warning %}} operationId: getContentOverrideName parameters: - $ref: '#/components/parameters/serverName' @@ -304,10 +330,23 @@ paths: - Media "/media/v3/thumbnail/{serverName}/{mediaId}": get: + deprecated: true summary: Download a thumbnail of content from the content repository description: |- + {{% boxes/note %}} + Replaced by [`GET /_matrix/client/v1/media/thumbnail/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid) + (requires authentication). + {{% /boxes/note %}} + Download a thumbnail of content from the content repository. See the [Thumbnails](/client-server-api/#thumbnails) section for more information. + + {{% boxes/warning %}} + {{< changed-in v="1.11" >}} This endpoint MAY return `404 M_NOT_FOUND` + for media which exists, but is after the server froze unauthenticated + media access. See [Client Behaviour](/client-server-api/#content-repo-client-behaviour) for more + information. + {{% /boxes/warning %}} operationId: getContentThumbnail parameters: - $ref: '#/components/parameters/serverName' @@ -455,8 +494,13 @@ paths: - Media /media/v3/preview_url: get: + deprecated: true summary: Get information about a URL for a client description: |- + {{% boxes/note %}} + Replaced by [`GET /_matrix/client/v1/media/preview_url`](/client-server-api/#get_matrixclientv1mediapreview_url). + {{% /boxes/note %}} + Get information about a URL for the client. Typically this is called when a client sees a URL in a message and wants to render a preview for the user. @@ -525,8 +569,13 @@ paths: - Media /media/v3/config: get: + deprecated: true summary: Get the configuration for the content repository. description: |- + {{% boxes/note %}} + Replaced by [`GET /_matrix/client/v1/media/config`](/client-server-api/#get_matrixclientv1mediaconfig). + {{% /boxes/note %}} + This endpoint allows clients to retrieve the configuration of the content repository, such as upload limitations. Clients SHOULD use this as a guide when using content repository endpoints. @@ -625,7 +674,7 @@ components: Indicates to the server that it should not attempt to fetch the media if it is deemed remote. This is to prevent routing loops where the server contacts itself. - + Defaults to `true` if not provided. example: false schema: diff --git a/data/api/client-server/definitions/sso_login_flow.yaml b/data/api/client-server/definitions/sso_login_flow.yaml index 3b95e6642..0996511eb 100644 --- a/data/api/client-server/definitions/sso_login_flow.yaml +++ b/data/api/client-server/definitions/sso_login_flow.yaml @@ -53,6 +53,18 @@ properties: description: |- Optional `mxc://` URI to provide an image/icon representing the IdP. Intended to be shown alongside the `name` if provided. + + {{% boxes/note %}} + Clients SHOULD use the deprecated [`/download`](/client-server-api/#get_matrixmediav3downloadservernamemediaid) + and [`/thumbnail`](/client-server-api/#get_matrixmediav3thumbnailservernamemediaid) + endpoints to retrieve this media item because clients will not have + an access token they can authenticate with yet. Servers SHOULD ensure + media used for IdP icons is excluded from the freeze described by the + [Content Repository module's Client Behaviour section](/client-server-api/#content-repo-client-behaviour). + + This may be addressed in the future with proposals like [MSC4148](https://github.com/matrix-org/matrix-spec-proposals/pull/4148), + or removed entirely through the transition to OIDC. + {{% /boxes/note %}} example: "mxc://example.org/abc123" brand: type: string diff --git a/data/api/server-server/content_repository.yaml b/data/api/server-server/content_repository.yaml new file mode 100644 index 000000000..6c19d6ec9 --- /dev/null +++ b/data/api/server-server/content_repository.yaml @@ -0,0 +1,303 @@ +# Copyright 2024 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +openapi: 3.1.0 +info: + title: Matrix Federation Content Repository API + version: 1.0.0 +paths: + "/media/download/{mediaId}": + get: + x-addedInMatrixVersion: "1.11" + summary: Download content from the content repository. + operationId: getContent + security: + - signedRequest: [] + parameters: + - $ref: '#/components/parameters/mediaId' + - $ref: '#/components/parameters/timeout_ms' + responses: + "200": + description: The content that was previously uploaded. + headers: + Content-Type: + $ref: '#/components/headers/downloadContentType' + content: + multipart/mixed: + schema: + # This is a workaround for us not being able to say the response is required. + description: |- + **Required.** MUST contain a `boundary` (per [RFC 1341](https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html)) + delineating exactly two parts: + + The first part has a `Content-Type` header of `application/json` + and describes the media's metadata, if any. Currently, this will + always be an empty object. + + The second part is either: + + 1. the bytes of the media itself, using `Content-Type` and + `Content-Disposition` headers as appropriate; + 2. or a `Location` header to redirect the caller to where the media + can be retrieved. The URL at `Location` SHOULD have appropriate + `Content-Type` and `Content-Disposition` headers which describe + the media. + + When `Location` is present, servers SHOULD NOT cache the URL. + The remote server may have applied time limits on its validity. + If the caller requires an up-to-date URL, it SHOULD re-request + the media download. + "429": + $ref: '#/components/responses/rateLimited' + "502": + description: The content is too large for the server to serve. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to serve" + } + "504": + $ref: '#/components/responses/notYetUploaded' + tags: + - Media + "/media/thumbnail/{mediaId}": + get: + x-addedInMatrixVersion: "1.11" + summary: Download a thumbnail of content from the content repository + description: |- + Download a thumbnail of content from the content repository. + See the [Client-Server API Thumbnails](/client-server-api/#thumbnails) + section for more information. + operationId: getContentThumbnail + security: + - signedRequest: [] + parameters: + - $ref: '#/components/parameters/mediaId' + - in: query + name: width + required: true + description: |- + The *desired* width of the thumbnail. The actual thumbnail may be + larger than the size specified. + example: 64 + schema: + type: integer + - in: query + name: height + required: true + description: |- + The *desired* height of the thumbnail. The actual thumbnail may be + larger than the size specified. + example: 64 + schema: + type: integer + - in: query + name: method + description: |- + The desired resizing method. See the [Client-Server API Thumbnails](/client-server-api/#thumbnails) + section for more information. + example: scale + schema: + type: string + enum: + - crop + - scale + - $ref: '#/components/parameters/timeout_ms' + - in: query + name: animated + x-addedInMatrixVersion: "1.11" + required: false + description: | + Indicates preference for an animated thumbnail from the server, if possible. Animated + thumbnails typically use the content types `image/gif`, `image/png` (with APNG format), + `image/apng`, and `image/webp` instead of the common static `image/png` or `image/jpeg` + content types. + + When `true`, the server SHOULD return an animated thumbnail if possible and supported. + When `false`, the server MUST NOT return an animated thumbnail. For example, returning a + static `image/png` or `image/jpeg` thumbnail. When not provided, the server SHOULD NOT + return an animated thumbnail. + + Servers SHOULD prefer to return `image/webp` thumbnails when supporting animation. + + When `true` and the media cannot be animated, such as in the case of a JPEG or PDF, the + server should behave as though `animated` is `false`. + example: false + schema: + type: boolean + responses: + "200": + description: A thumbnail of the requested content. + headers: + Content-Type: + description: Must be `multipart/mixed`. + schema: + type: string + content: + multipart/mixed: + schema: + # This is a workaround for us not being able to say the response is required. + description: |- + **Required.** MUST contain a `boundary` (per [RFC 1341](https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html)) + delineating exactly two parts: + + The first part has a `Content-Type` header of `application/json` + and describes the media's metadata, if any. Currently, this will + always be an empty object. + + The second part is either: + + 1. the bytes of the media itself, using `Content-Type` and + `Content-Disposition` headers as appropriate; + 2. or a `Location` header to redirect the caller to where the media + can be retrieved. The URL at `Location` SHOULD have appropriate + `Content-Type` and `Content-Disposition` headers which describe + the media. + + When `Location` is present, servers SHOULD NOT cache the URL. + The remote server may have applied time limits on its validity. + If the caller requires an up-to-date URL, it SHOULD re-request + the media download. + + {{% boxes/note %}} + The `Content-Type` for the second part SHOULD be one of: + * `image/png` (possibly of the APNG variety) + * `image/apng` + * `image/jpeg` + * `image/gif` + * `image/webp` + {{% /boxes/note %}} + "400": + description: |- + The request does not make sense to the server, or the server cannot thumbnail + the content. For example, the caller requested non-integer dimensions or asked + for negatively-sized images. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_UNKNOWN", + "error": "Cannot generate thumbnails for the requested content" + } + "413": + description: The local content is too large for the server to thumbnail. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to thumbnail" + } + "429": + $ref: '#/components/responses/rateLimited' + "502": + description: The remote content is too large for the server to thumbnail. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_TOO_LARGE", + "error": "Content is too large to thumbnail" + } + "504": + $ref: '#/components/responses/notYetUploaded' + tags: + - Media +servers: + - url: "{protocol}://{hostname}{basePath}" + variables: + protocol: + enum: + - http + - https + default: https + hostname: + default: localhost:8448 + basePath: + default: /_matrix/federation/v1 +components: + securitySchemes: + signedRequest: + $ref: definitions/security.yaml#/signedRequest + parameters: + mediaId: + in: path + name: mediaId + required: true + description: | + The media ID from the `mxc://` URI (the path component). + example: ascERGshawAWawugaAcauga + schema: + type: string + timeout_ms: + in: query + name: timeout_ms + x-addedInMatrixVersion: "1.7" + description: | + The maximum number of milliseconds that the client is willing to wait to + start receiving data, in the case that the content has not yet been + uploaded. The default value is 20000 (20 seconds). The content + repository can and should impose a maximum value for this parameter. The + content repository may also choose to respond before the timeout. + example: 5000 + schema: + type: integer + format: int64 + default: 20000 + responses: + rateLimited: + description: This request was rate-limited. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/rate_limited.yaml + notYetUploaded: + description: |- + The content is not yet available. A [standard error response](/client-server-api/#standard-error-response) + will be returned with the `errcode` `M_NOT_YET_UPLOADED`. + content: + application/json: + schema: + # XXX: We should move error definitions into a more generic place. + $ref: ../client-server/definitions/errors/error.yaml + examples: + response: + value: { + "errcode": "M_NOT_YET_UPLOADED", + "error": "Content has not yet been uploaded" + } + headers: + downloadContentType: + description: |- + Must be `multipart/mixed`. + schema: + type: string