Skip to content

Commit

Permalink
Support optional MSC3860 redirects (#4007)
Browse files Browse the repository at this point in the history
* Support optional MSC3860 redirects

See `allow_redirect` across the media endpoints: https://spec.matrix.org/v1.9/client-server-api/#client-behaviour-7

* Update the tests

* Appease the linter

* Add test to appease SonarCloud
  • Loading branch information
turt2live authored Jan 15, 2024
1 parent 2ef3ebb commit e47136c
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
27 changes: 23 additions & 4 deletions spec/unit/content-repo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,22 @@ describe("ContentRepo", function () {
it("should return a download URL if no width/height/resize are specified", function () {
const mxcUri = "mxc://server.name/resourceid";
expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual(
baseUrl + "/_matrix/media/v3/download/server.name/resourceid",
baseUrl + "/_matrix/media/v3/download/server.name/resourceid?allow_redirect=false",
);
});

it("should allow redirects when requested on download URLs", function () {
const mxcUri = "mxc://server.name/resourceid";
expect(getHttpUriForMxc(baseUrl, mxcUri, undefined, undefined, undefined, false, true)).toEqual(
baseUrl + "/_matrix/media/v3/download/server.name/resourceid?allow_redirect=true",
);
});

it("should allow redirects when requested on thumbnail URLs", function () {
const mxcUri = "mxc://server.name/resourceid";
expect(getHttpUriForMxc(baseUrl, mxcUri, 32, 32, "scale", false, true)).toEqual(
baseUrl +
"/_matrix/media/v3/thumbnail/server.name/resourceid?width=32&height=32&method=scale&allow_redirect=true",
);
});

Expand All @@ -44,21 +59,25 @@ describe("ContentRepo", function () {
it("should return a thumbnail URL if a width/height/resize is specified", function () {
const mxcUri = "mxc://server.name/resourceid";
expect(getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual(
baseUrl + "/_matrix/media/v3/thumbnail/server.name/resourceid" + "?width=32&height=64&method=crop",
baseUrl +
"/_matrix/media/v3/thumbnail/server.name/resourceid" +
"?width=32&height=64&method=crop&allow_redirect=false",
);
});

it("should put fragments from mxc:// URIs after any query parameters", function () {
const mxcUri = "mxc://server.name/resourceid#automade";
expect(getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual(
baseUrl + "/_matrix/media/v3/thumbnail/server.name/resourceid" + "?width=32#automade",
baseUrl +
"/_matrix/media/v3/thumbnail/server.name/resourceid" +
"?width=32&allow_redirect=false#automade",
);
});

it("should put fragments from mxc:// URIs at the end of the HTTP URI", function () {
const mxcUri = "mxc://server.name/resourceid#automade";
expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual(
baseUrl + "/_matrix/media/v3/download/server.name/resourceid#automade",
baseUrl + "/_matrix/media/v3/download/server.name/resourceid?allow_redirect=false#automade",
);
});
});
Expand Down
16 changes: 16 additions & 0 deletions spec/unit/matrix-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
RuleId,
IPushRule,
ConditionKind,
getHttpUriForMxc,
} from "../../src";
import { supportsMatrixCall } from "../../src/webrtc/call";
import { makeBeaconEvent } from "../test-utils/beacon";
Expand Down Expand Up @@ -369,6 +370,21 @@ describe("MatrixClient", function () {
client.stopClient();
});

describe("mxcUrlToHttp", () => {
it("should call getHttpUriForMxc", () => {
const mxc = "mxc://server/example";
expect(client.mxcUrlToHttp(mxc)).toBe(getHttpUriForMxc(client.baseUrl, mxc));
expect(client.mxcUrlToHttp(mxc, 32)).toBe(getHttpUriForMxc(client.baseUrl, mxc, 32));
expect(client.mxcUrlToHttp(mxc, 32, 46)).toBe(getHttpUriForMxc(client.baseUrl, mxc, 32, 46));
expect(client.mxcUrlToHttp(mxc, 32, 46, "scale")).toBe(
getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale"),
);
expect(client.mxcUrlToHttp(mxc, 32, 46, "scale", false, true)).toBe(
getHttpUriForMxc(client.baseUrl, mxc, 32, 46, "scale", false, true),
);
});
});

describe("timestampToEvent", () => {
const roomId = "!room:server.org";
const eventId = "$eventId:example.org";
Expand Down
6 changes: 5 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5683,6 +5683,9 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
* @param allowDirectLinks - If true, return any non-mxc URLs
* directly. Fetching such URLs will leak information about the user to
* 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
* 308 redirected to another resource upon request. If false (default), redirects
* are not expected.
* @returns the avatar URL or null.
*/
public mxcUrlToHttp(
Expand All @@ -5691,8 +5694,9 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
height?: number,
resizeMethod?: string,
allowDirectLinks?: boolean,
allowRedirects?: boolean,
): string | null {
return getHttpUriForMxc(this.baseUrl, mxcUrl, width, height, resizeMethod, allowDirectLinks);
return getHttpUriForMxc(this.baseUrl, mxcUrl, width, height, resizeMethod, allowDirectLinks, allowRedirects);
}

/**
Expand Down
4 changes: 4 additions & 0 deletions src/content-repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function getHttpUriForMxc(
height?: number,
resizeMethod?: string,
allowDirectLinks = false,
allowRedirects = false,
): string {
if (typeof mxc !== "string" || !mxc) {
return "";
Expand Down Expand Up @@ -67,6 +68,9 @@ export function getHttpUriForMxc(
prefix = "/_matrix/media/v3/thumbnail/";
}

// We add this after so we don't convert everything to a thumbnail request.
params["allow_redirect"] = JSON.stringify(allowRedirects);

const fragmentOffset = serverAndMediaId.indexOf("#");
let fragment = "";
if (fragmentOffset >= 0) {
Expand Down

0 comments on commit e47136c

Please sign in to comment.