Add authenticated media (MSC3916) (#1858)

* C2S: Deprecate now-legacy endpoints

* C2S: Fix MXC URI code block while we're here

* C2S: Describe the authentication and deprecation requirements

* C2S: Intro the upload/download endpoints differently

* C2S: Literally copy/paste the `content-repo.yaml` spec

* C2S: Drop `/upload` and `/create` because we aren't replacing them today

* C2S: Fix notes while we're here

* C2S: Update metadata for new endpoints

* C2S: Add authentication to new endpoints

* C2S: Drop `allow_remote` and `allow_redirect` on new endpoints

* C2S: Append backwards compatibility notes

* C2S: Decorate old media endpoints with pointers to the new ones

The server-server spec might have a harder time linking to these, but that can be fixed with verbiage.

* C2S: Annotate IdP icon spec with media auth implications

* S2S: Modernize section text

* S2S: Create content repository API

This is largely a copy/paste of the new authed content repo API in the Client-Server API, though some keywords (like "client") have been changed. Paths and response formats have also been changed to support the federation-specific requirements.

* C2S & S2S: Add plethora of changelogs

* Reference RFC 1341

* Upgrade keywords in changed text

* Mention caching

* Cross-reference IdP icons

* Update content/client-server-api/modules/content_repo.md
pull/1861/head
Travis Ralston 5 months ago committed by GitHub
parent 4a280bcd87
commit 7a51ae879c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1 @@
Use of the `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead.

@ -0,0 +1 @@
Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916).

@ -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).

@ -0,0 +1 @@
[`GET /_matrix/client/v1/media/config`](/client-server-api/#get_matrixclientv1mediaconfig)

@ -0,0 +1 @@
[`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaid)

@ -0,0 +1 @@
[`GET /_matrix/client/v1/media/download/{serverName}/{mediaId}/{fileName}`](/client-server-api/#get_matrixclientv1mediadownloadservernamemediaidfilename)

@ -0,0 +1 @@
[`GET /_matrix/client/v1/media/preview_url`](/client-server-api/#get_matrixclientv1mediapreview_url)

@ -0,0 +1 @@
[`GET /_matrix/client/v1/media/thumbnail/{serverName}/{mediaId}`](/client-server-api/#get_matrixclientv1mediathumbnailservernamemediaid)

@ -0,0 +1 @@
Use of the Client-Server API `/_matrix/media/*` endpoints is now deprecated. New, authenticated, endpoints are available instead.

@ -0,0 +1 @@
Media downloads and thumbnails are now authenticated, as per [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916).

@ -0,0 +1 @@
[`GET /_matrix/federation/v1/media/download/{mediaId}`](/server-server-api/#get_matrixfederationv1mediadownloadmediaid)

@ -0,0 +1 @@
[`GET /_matrix/federation/v1/media/thumbnail/{mediaId}`](/server-server-api/#get_matrixfederationv1mediathumbnailmediaid)

@ -37,9 +37,8 @@ The exceptions are:
which take an empty request body. which take an empty request body.
Similarly, all endpoints require the server to return a JSON object, Similarly, all endpoints require the server to return a JSON object,
with the exception of 200 responses to with the exception of 200 responses to the media download endpoints in the
[`GET /_matrix/media/v3/download/{serverName}/{mediaId}`](#get_matrixmediav3downloadservernamemediaid) [Content Repository module](#content-repository).
and [`GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}`](#get_matrixmediav3thumbnailservernamemediaid).
Servers must include a `Content-Type` header of `application/json` for all JSON responses. 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. All JSON data, in requests or responses, must be encoded using UTF-8.

@ -23,19 +23,67 @@ When serving content, the server SHOULD provide a
interacting with the media repository. interacting with the media repository.
{{% /boxes/added-in-paragraph %}} {{% /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 #### Matrix Content (`mxc://`) URIs
Content locations are represented as Matrix Content (`mxc://`) URIs. They Content locations are represented as Matrix Content (`mxc://`) URIs. They
look like: look like:
mxc://<server-name>/<media-id> ```
mxc://<server-name>/<media-id>
<server-name> : The name of the homeserver where this content originated, e.g. matrix.org
<media-id> : 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:
<server-name> : The name of the homeserver where this content originated, e.g. matrix.org * Matrix 1.11 release: Clients begin supporting authenticated media.
<media-id> : An opaque ID which identifies the content. * 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" %}} {{% http-api spec="client-server" api="content-repo" %}}

@ -1196,15 +1196,26 @@ using the following EDU:
Attachments to events (images, files, etc) are uploaded to a homeserver Attachments to events (images, files, etc) are uploaded to a homeserver
via the Content Repository described in the [Client-Server 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 to serve content originating from a remote server, it needs to ask the
remote server for the media. remote server for the media.
Servers should use the server described in the Matrix Content URI, which Servers MUST use the server described in the [Matrix Content URI](/client-server-api/#matrix-content-mxc-uris).
has the format `mxc://{ServerName}/{MediaID}`. Servers should use the Formatted as `mxc://{ServerName}/{MediaID}`, servers MUST download the media from
download endpoint described in the [Client-Server `ServerName` using the below endpoints.
API](/client-server-api), being sure to use
the `allow_remote` parameter (set to `false`). {{% 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) ## Server Access Control Lists (ACLs)

@ -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

@ -217,7 +217,20 @@ paths:
- Media - Media
"/media/v3/download/{serverName}/{mediaId}": "/media/v3/download/{serverName}/{mediaId}":
get: get:
deprecated: true
summary: Download content from the content repository. 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 operationId: getContent
parameters: parameters:
- $ref: '#/components/parameters/serverName' - $ref: '#/components/parameters/serverName'
@ -254,11 +267,24 @@ paths:
- Media - Media
"/media/v3/download/{serverName}/{mediaId}/{fileName}": "/media/v3/download/{serverName}/{mediaId}/{fileName}":
get: get:
deprecated: true
summary: Download content from the content repository overriding the file name summary: Download content from the content repository overriding the file name
description: |- 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 This will download content from the content repository (same as
the previous endpoint) but replace the target file name with the one the previous endpoint) but replace the target file name with the one
provided by the caller. 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 operationId: getContentOverrideName
parameters: parameters:
- $ref: '#/components/parameters/serverName' - $ref: '#/components/parameters/serverName'
@ -304,10 +330,23 @@ paths:
- Media - Media
"/media/v3/thumbnail/{serverName}/{mediaId}": "/media/v3/thumbnail/{serverName}/{mediaId}":
get: get:
deprecated: true
summary: Download a thumbnail of content from the content repository summary: Download a thumbnail of content from the content repository
description: |- 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. Download a thumbnail of content from the content repository.
See the [Thumbnails](/client-server-api/#thumbnails) section for more information. 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 operationId: getContentThumbnail
parameters: parameters:
- $ref: '#/components/parameters/serverName' - $ref: '#/components/parameters/serverName'
@ -455,8 +494,13 @@ paths:
- Media - Media
/media/v3/preview_url: /media/v3/preview_url:
get: get:
deprecated: true
summary: Get information about a URL for a client summary: Get information about a URL for a client
description: |- 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 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. client sees a URL in a message and wants to render a preview for the user.
@ -525,8 +569,13 @@ paths:
- Media - Media
/media/v3/config: /media/v3/config:
get: get:
deprecated: true
summary: Get the configuration for the content repository. summary: Get the configuration for the content repository.
description: |- 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 This endpoint allows clients to retrieve the configuration of the content
repository, such as upload limitations. repository, such as upload limitations.
Clients SHOULD use this as a guide when using content repository endpoints. Clients SHOULD use this as a guide when using content repository endpoints.

@ -53,6 +53,18 @@ properties:
description: |- description: |-
Optional `mxc://` URI to provide an image/icon representing the IdP. Optional `mxc://` URI to provide an image/icon representing the IdP.
Intended to be shown alongside the `name` if provided. 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" example: "mxc://example.org/abc123"
brand: brand:
type: string type: string

@ -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
Loading…
Cancel
Save