You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-07-31 15:24:23 +03:00
Add helpers for authenticated media, and associated documentation (#4185)
* Add helpers for authenticated media, and associated documentation * Appease the linter
This commit is contained in:
32
README.md
32
README.md
@ -21,6 +21,10 @@ endpoints from before Matrix 1.1, for example.
|
|||||||
|
|
||||||
# Quickstart
|
# Quickstart
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Servers may require or use authenticated endpoints for media (images, files, avatars, etc). See the
|
||||||
|
> [Authenticated Media](#authenticated-media) section for information on how to enable support for this.
|
||||||
|
|
||||||
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install guide](https://classic.yarnpkg.com/en/docs/install)
|
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install guide](https://classic.yarnpkg.com/en/docs/install)
|
||||||
if you do not have it already.
|
if you do not have it already.
|
||||||
|
|
||||||
@ -89,6 +93,34 @@ Object.keys(client.store.rooms).forEach((roomId) => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Authenticated media
|
||||||
|
|
||||||
|
Servers supporting [MSC3916](https://github.com/matrix-org/matrix-spec-proposals/pull/3916) will require clients, like
|
||||||
|
yours, to include an `Authorization` header when `/download`ing or `/thumbnail`ing media. For NodeJS environments this
|
||||||
|
may be as easy as the following code snippet, though web browsers may need to use [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)
|
||||||
|
to append the header when using the endpoints in `<img />` elements and similar.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const downloadUrl = client.mxcUrlToHttp(
|
||||||
|
/*mxcUrl=*/ "mxc://example.org/abc123", // the MXC URI to download/thumbnail, typically from an event or profile
|
||||||
|
/*width=*/ undefined, // part of the thumbnail API. Use as required.
|
||||||
|
/*height=*/ undefined, // part of the thumbnail API. Use as required.
|
||||||
|
/*resizeMethod=*/ undefined, // part of the thumbnail API. Use as required.
|
||||||
|
/*allowDirectLinks=*/ false, // should generally be left `false`.
|
||||||
|
/*allowRedirects=*/ true, // implied supported with authentication
|
||||||
|
/*useAuthentication=*/ true, // the flag we're after in this example
|
||||||
|
);
|
||||||
|
const img = await fetch(downloadUrl, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${client.getAccessToken()}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Do something with `img`.
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> In future the js-sdk will _only_ return authentication-required URLs, mandating population of the `Authorization` header.
|
||||||
|
|
||||||
## What does this SDK do?
|
## What does this SDK do?
|
||||||
|
|
||||||
This SDK provides a full object model around the Matrix Client-Server API and emits
|
This SDK provides a full object model around the Matrix Client-Server API and emits
|
||||||
|
@ -76,5 +76,29 @@ describe("ContentRepo", function () {
|
|||||||
baseUrl + "/_matrix/media/v3/download/server.name/resourceid#automade",
|
baseUrl + "/_matrix/media/v3/download/server.name/resourceid#automade",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return an authenticated URL when requested", function () {
|
||||||
|
const mxcUri = "mxc://server.name/resourceid";
|
||||||
|
expect(getHttpUriForMxc(baseUrl, mxcUri, undefined, undefined, undefined, undefined, true, true)).toEqual(
|
||||||
|
baseUrl +
|
||||||
|
"/_matrix/client/unstable/org.matrix.msc3916/media/download/server.name/resourceid?allow_redirect=true",
|
||||||
|
);
|
||||||
|
expect(getHttpUriForMxc(baseUrl, mxcUri, 64, 64, "scale", undefined, true, true)).toEqual(
|
||||||
|
baseUrl +
|
||||||
|
"/_matrix/client/unstable/org.matrix.msc3916/media/thumbnail/server.name/resourceid?width=64&height=64&method=scale&allow_redirect=true",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should force-enable allow_redirects when useAuthentication is set true", function () {
|
||||||
|
const mxcUri = "mxc://server.name/resourceid";
|
||||||
|
expect(getHttpUriForMxc(baseUrl, mxcUri, undefined, undefined, undefined, undefined, false, true)).toEqual(
|
||||||
|
baseUrl +
|
||||||
|
"/_matrix/client/unstable/org.matrix.msc3916/media/download/server.name/resourceid?allow_redirect=true",
|
||||||
|
);
|
||||||
|
expect(getHttpUriForMxc(baseUrl, mxcUri, 64, 64, "scale", undefined, false, true)).toEqual(
|
||||||
|
baseUrl +
|
||||||
|
"/_matrix/client/unstable/org.matrix.msc3916/media/thumbnail/server.name/resourceid?width=64&height=64&method=scale&allow_redirect=true",
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -386,6 +386,9 @@ describe("MatrixClient", function () {
|
|||||||
expect(client.mxcUrlToHttp(mxc, 32, 46, "scale", false, true)).toBe(
|
expect(client.mxcUrlToHttp(mxc, 32, 46, "scale", false, true)).toBe(
|
||||||
getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale", false, true),
|
getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale", false, true),
|
||||||
);
|
);
|
||||||
|
expect(client.mxcUrlToHttp(mxc, 32, 46, "scale", false, true, true)).toBe(
|
||||||
|
getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale", false, true, true),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5775,7 +5775,12 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
* anyone they share a room with. If false, will return null for such URLs.
|
* anyone they share a room with. If false, will return null for such URLs.
|
||||||
* @param allowRedirects - If true, the caller supports the URL being 307 or
|
* @param allowRedirects - If true, the caller supports the URL being 307 or
|
||||||
* 308 redirected to another resource upon request. If false, redirects
|
* 308 redirected to another resource upon request. If false, redirects
|
||||||
* are not expected.
|
* are not expected. Implied `true` when `useAuthentication` is `true`.
|
||||||
|
* @param useAuthentication - If true, the caller supports authenticated
|
||||||
|
* media and wants an authentication-required URL. Note that server support
|
||||||
|
* for authenticated media will *not* be checked - it is the caller's responsibility
|
||||||
|
* to do so before calling this function. Note also that `useAuthentication`
|
||||||
|
* implies `allowRedirects`. Defaults to false (unauthenticated endpoints).
|
||||||
* @returns the avatar URL or null.
|
* @returns the avatar URL or null.
|
||||||
*/
|
*/
|
||||||
public mxcUrlToHttp(
|
public mxcUrlToHttp(
|
||||||
@ -5785,8 +5790,18 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
|
|||||||
resizeMethod?: string,
|
resizeMethod?: string,
|
||||||
allowDirectLinks?: boolean,
|
allowDirectLinks?: boolean,
|
||||||
allowRedirects?: boolean,
|
allowRedirects?: boolean,
|
||||||
|
useAuthentication?: boolean,
|
||||||
): string | null {
|
): string | null {
|
||||||
return getHttpUriForMxc(this.baseUrl, mxcUrl, width, height, resizeMethod, allowDirectLinks, allowRedirects);
|
return getHttpUriForMxc(
|
||||||
|
this.baseUrl,
|
||||||
|
mxcUrl,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
resizeMethod,
|
||||||
|
allowDirectLinks,
|
||||||
|
allowRedirects,
|
||||||
|
useAuthentication,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +30,12 @@ import { encodeParams } from "./utils";
|
|||||||
* for such URLs.
|
* for such URLs.
|
||||||
* @param allowRedirects - If true, the caller supports the URL being 307 or
|
* @param allowRedirects - If true, the caller supports the URL being 307 or
|
||||||
* 308 redirected to another resource upon request. If false, redirects
|
* 308 redirected to another resource upon request. If false, redirects
|
||||||
* are not expected.
|
* are not expected. Implied `true` when `useAuthentication` is `true`.
|
||||||
|
* @param useAuthentication - If true, the caller supports authenticated
|
||||||
|
* media and wants an authentication-required URL. Note that server support
|
||||||
|
* for authenticated media will *not* be checked - it is the caller's responsibility
|
||||||
|
* to do so before calling this function. Note also that `useAuthentication`
|
||||||
|
* implies `allowRedirects`. Defaults to false (unauthenticated endpoints).
|
||||||
* @returns The complete URL to the content.
|
* @returns The complete URL to the content.
|
||||||
*/
|
*/
|
||||||
export function getHttpUriForMxc(
|
export function getHttpUriForMxc(
|
||||||
@ -41,6 +46,7 @@ export function getHttpUriForMxc(
|
|||||||
resizeMethod?: string,
|
resizeMethod?: string,
|
||||||
allowDirectLinks = false,
|
allowDirectLinks = false,
|
||||||
allowRedirects?: boolean,
|
allowRedirects?: boolean,
|
||||||
|
useAuthentication?: boolean,
|
||||||
): string {
|
): string {
|
||||||
if (typeof mxc !== "string" || !mxc) {
|
if (typeof mxc !== "string" || !mxc) {
|
||||||
return "";
|
return "";
|
||||||
@ -52,8 +58,23 @@ export function getHttpUriForMxc(
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useAuthentication) {
|
||||||
|
allowRedirects = true; // per docs (MSC3916 always expects redirects)
|
||||||
|
|
||||||
|
// Dev note: MSC3916 (as of writing) removes `allow_redirect` entirely, but
|
||||||
|
// for explicitness we set it here. This makes it slightly more obvious to
|
||||||
|
// callers, hopefully.
|
||||||
|
}
|
||||||
|
|
||||||
let serverAndMediaId = mxc.slice(6); // strips mxc://
|
let serverAndMediaId = mxc.slice(6); // strips mxc://
|
||||||
let prefix = "/_matrix/media/v3/download/";
|
let prefix: string;
|
||||||
|
if (useAuthentication) {
|
||||||
|
// TODO: Use stable once available (requires FCP on MSC3916).
|
||||||
|
prefix = "/_matrix/client/unstable/org.matrix.msc3916/media/download/";
|
||||||
|
} else {
|
||||||
|
prefix = "/_matrix/media/v3/download/";
|
||||||
|
}
|
||||||
const params: Record<string, string> = {};
|
const params: Record<string, string> = {};
|
||||||
|
|
||||||
if (width) {
|
if (width) {
|
||||||
@ -68,7 +89,12 @@ export function getHttpUriForMxc(
|
|||||||
if (Object.keys(params).length > 0) {
|
if (Object.keys(params).length > 0) {
|
||||||
// these are thumbnailing params so they probably want the
|
// these are thumbnailing params so they probably want the
|
||||||
// thumbnailing API...
|
// thumbnailing API...
|
||||||
prefix = "/_matrix/media/v3/thumbnail/";
|
if (useAuthentication) {
|
||||||
|
// TODO: Use stable once available (requires FCP on MSC3916).
|
||||||
|
prefix = "/_matrix/client/unstable/org.matrix.msc3916/media/thumbnail/";
|
||||||
|
} else {
|
||||||
|
prefix = "/_matrix/media/v3/thumbnail/";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof allowRedirects === "boolean") {
|
if (typeof allowRedirects === "boolean") {
|
||||||
|
Reference in New Issue
Block a user