mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-11-21 05:53:11 -05:00
Fix pagination URLs when behind SSL-terminating reverse proxy
This commit is contained in:
parent
f4b1ab5fa0
commit
5e63b57440
@ -256,7 +256,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
status,
|
||||
@ -294,7 +294,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
userId: sub,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get entries of a serie" },
|
||||
@ -338,6 +338,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
jwt: { sub },
|
||||
status,
|
||||
}) => {
|
||||
@ -373,7 +374,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
userId: sub,
|
||||
})) as Extra[];
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get extras of a serie" },
|
||||
@ -410,6 +411,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
async ({
|
||||
query: { limit, after, query, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
const sort = newsSort;
|
||||
@ -427,7 +429,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
||||
userId: sub,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get new movies/episodes added recently." },
|
||||
|
||||
@ -67,7 +67,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
"/profiles/me/history",
|
||||
async ({
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
@ -87,7 +87,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
progressQ: historyProgressQ,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
@ -109,7 +109,11 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages, authorization },
|
||||
headers: {
|
||||
"accept-language": languages,
|
||||
authorization,
|
||||
...headers
|
||||
},
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
@ -132,7 +136,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
||||
progressQ: historyProgressQ,
|
||||
})) as Entry[];
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
|
||||
@ -69,7 +69,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
"/profiles/me/nextup",
|
||||
async ({
|
||||
query: { sort, filter, query, limit, after },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub },
|
||||
}) => {
|
||||
@ -124,7 +124,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
||||
.limit(limit)
|
||||
.execute({ userId: sub });
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
|
||||
@ -142,7 +142,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
"/profiles/me/watchlist",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
@ -162,7 +162,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
relations: ["nextEntry"],
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies/series in your watchlist" },
|
||||
@ -195,7 +195,11 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
jwt: { settings },
|
||||
headers: { "accept-language": languages, authorization },
|
||||
headers: {
|
||||
"accept-language": languages,
|
||||
authorization,
|
||||
...headers
|
||||
},
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
@ -218,7 +222,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
||||
relations: ["nextEntry"],
|
||||
userId: uInfo.id,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
|
||||
@ -53,7 +53,7 @@ export const seasonsH = new Elysia({ tags: ["series"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
status,
|
||||
}) => {
|
||||
@ -110,7 +110,7 @@ export const seasonsH = new Elysia({ tags: ["series"] })
|
||||
)
|
||||
.limit(limit);
|
||||
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get seasons of a serie" },
|
||||
|
||||
@ -143,7 +143,7 @@ export const collections = new Elysia({
|
||||
"",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
}) => {
|
||||
@ -158,7 +158,7 @@ export const collections = new Elysia({
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all collections" },
|
||||
@ -227,7 +227,7 @@ export const collections = new Elysia({
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -265,7 +265,7 @@ export const collections = new Elysia({
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies in a collection" },
|
||||
@ -284,7 +284,7 @@ export const collections = new Elysia({
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -322,7 +322,7 @@ export const collections = new Elysia({
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all series in a collection" },
|
||||
@ -341,7 +341,7 @@ export const collections = new Elysia({
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -375,7 +375,7 @@ export const collections = new Elysia({
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all series & movies in a collection" },
|
||||
|
||||
@ -133,7 +133,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
|
||||
"",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
@ -148,7 +148,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies" },
|
||||
|
||||
@ -136,7 +136,7 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
|
||||
"",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
@ -151,7 +151,7 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all series" },
|
||||
|
||||
@ -63,7 +63,7 @@ export const showsH = new Elysia({ prefix: "/shows", tags: ["shows"] })
|
||||
preferOriginal,
|
||||
ignoreInCollection,
|
||||
},
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
}) => {
|
||||
@ -81,7 +81,7 @@ export const showsH = new Elysia({ prefix: "/shows", tags: ["shows"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies/series/collections" },
|
||||
|
||||
@ -189,7 +189,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
jwt: { sub, settings },
|
||||
status,
|
||||
@ -269,7 +269,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
roles.showPk,
|
||||
)
|
||||
.limit(limit);
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
@ -316,7 +316,11 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
)
|
||||
.get(
|
||||
"/staff",
|
||||
async ({ query: { limit, after, sort, query }, request: { url } }) => {
|
||||
async ({
|
||||
query: { limit, after, sort, query },
|
||||
request: { url },
|
||||
headers,
|
||||
}) => {
|
||||
const items = await db
|
||||
.select()
|
||||
.from(staff)
|
||||
@ -333,7 +337,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
staff.pk,
|
||||
)
|
||||
.limit(limit);
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
@ -362,6 +366,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
status,
|
||||
}) => {
|
||||
const [movie] = await db
|
||||
@ -389,7 +394,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
sort,
|
||||
filter: and(eq(roles.showPk, movie.pk), filter),
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
@ -429,6 +434,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter },
|
||||
request: { url },
|
||||
headers,
|
||||
status,
|
||||
}) => {
|
||||
const [serie] = await db
|
||||
@ -456,7 +462,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
||||
sort,
|
||||
filter: and(eq(roles.showPk, serie.pk), filter),
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
|
||||
@ -228,7 +228,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
"",
|
||||
async ({
|
||||
query: { limit, after, query, sort },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
request: { url },
|
||||
}) => {
|
||||
const langs = processLanguages(languages);
|
||||
@ -239,7 +239,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
sort,
|
||||
languages: langs,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all studios" },
|
||||
@ -302,7 +302,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -344,7 +344,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all series & movies made by a studio." },
|
||||
@ -363,7 +363,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -406,7 +406,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all movies made by a studio." },
|
||||
@ -425,7 +425,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
async ({
|
||||
params: { id },
|
||||
query: { limit, after, query, sort, filter, preferOriginal },
|
||||
headers: { "accept-language": languages },
|
||||
headers: { "accept-language": languages, ...headers },
|
||||
jwt: { sub, settings },
|
||||
request: { url },
|
||||
status,
|
||||
@ -468,7 +468,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||
userId: sub,
|
||||
});
|
||||
return createPage(items, { url, sort, limit });
|
||||
return createPage(items, { url, sort, limit, headers });
|
||||
},
|
||||
{
|
||||
detail: { description: "Get all series made by a studio." },
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { ObjectOptions } from "@sinclair/typebox";
|
||||
import { type TSchema, t } from "elysia";
|
||||
import { buildUrl } from "~/utils";
|
||||
import { generateAfter } from "./keyset-paginate";
|
||||
import type { Sort } from "./sort";
|
||||
|
||||
@ -18,11 +19,31 @@ export const Page = <T extends TSchema>(schema: T, options?: ObjectOptions) =>
|
||||
|
||||
export const createPage = <T>(
|
||||
items: T[],
|
||||
{ url, sort, limit }: { url: string; sort: Sort; limit: number },
|
||||
{
|
||||
url,
|
||||
sort,
|
||||
limit,
|
||||
headers,
|
||||
}: {
|
||||
url: string;
|
||||
sort: Sort;
|
||||
limit: number;
|
||||
headers?: Record<string, string | undefined>;
|
||||
},
|
||||
) => {
|
||||
let next: string | null = null;
|
||||
const uri = new URL(url);
|
||||
const forwardedProto = headers?.["x-forwarded-proto"];
|
||||
if (forwardedProto) {
|
||||
uri.protocol = forwardedProto;
|
||||
}
|
||||
const forwardedHost = headers?.["x-forwarded-host"];
|
||||
if (forwardedHost) {
|
||||
uri.host = forwardedHost;
|
||||
}
|
||||
|
||||
const current = uri.toString();
|
||||
|
||||
let next: string | null = null;
|
||||
if (sort.random) {
|
||||
uri.searchParams.set("sort", `random:${sort.random.seed}`);
|
||||
url = uri.toString();
|
||||
@ -35,5 +56,5 @@ export const createPage = <T>(
|
||||
uri.searchParams.set("after", generateAfter(items[items.length - 1], sort));
|
||||
next = uri.toString();
|
||||
}
|
||||
return { items, this: url, next };
|
||||
return { items, this: current, next };
|
||||
};
|
||||
|
||||
106
api/tests/misc/x-forwarded-headers.test.ts
Normal file
106
api/tests/misc/x-forwarded-headers.test.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { beforeAll, describe, expect, it } from "bun:test";
|
||||
import { getJwtHeaders } from "tests/helpers/jwt";
|
||||
import { expectStatus } from "tests/utils";
|
||||
import { db } from "~/db";
|
||||
import { shows } from "~/db/schema";
|
||||
import { bubble } from "~/models/examples";
|
||||
import { dune1984 } from "~/models/examples/dune-1984";
|
||||
import { dune } from "~/models/examples/dune-2021";
|
||||
import { createMovie, getMovies, handlers } from "../helpers";
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.delete(shows);
|
||||
for (const movie of [bubble, dune1984, dune]) {
|
||||
const [ret, _] = await createMovie(movie);
|
||||
expect(ret.status).toBe(201);
|
||||
}
|
||||
});
|
||||
|
||||
describe("X-Forwarded-Proto header support", () => {
|
||||
it("Pagination URLs use HTTPS when X-Forwarded-Proto is https", async () => {
|
||||
const resp = await handlers.handle(
|
||||
new Request("http://localhost/api/movies?limit=2", {
|
||||
headers: {
|
||||
...(await getJwtHeaders()),
|
||||
"x-forwarded-proto": "https",
|
||||
},
|
||||
}),
|
||||
);
|
||||
const body = await resp.json();
|
||||
|
||||
expectStatus(resp, body).toBe(200);
|
||||
expect(body).toMatchObject({
|
||||
items: expect.any(Array),
|
||||
this: "https://localhost/api/movies?limit=2",
|
||||
next: expect.stringContaining("https://localhost/api/movies?limit=2"),
|
||||
});
|
||||
});
|
||||
|
||||
it("Pagination URLs use HTTP when no X-Forwarded-Proto header", async () => {
|
||||
const [resp, body] = await getMovies({
|
||||
limit: 2,
|
||||
langs: "en",
|
||||
});
|
||||
|
||||
expectStatus(resp, body).toBe(200);
|
||||
expect(body).toMatchObject({
|
||||
items: expect.any(Array),
|
||||
this: "http://localhost/api/movies?limit=2",
|
||||
next: expect.stringContaining("http://localhost/api/movies?limit=2"),
|
||||
});
|
||||
});
|
||||
|
||||
it("X-Forwarded-Host header changes the host in pagination URLs", async () => {
|
||||
const resp = await handlers.handle(
|
||||
new Request("http://localhost/api/movies?limit=2", {
|
||||
headers: {
|
||||
...(await getJwtHeaders()),
|
||||
"x-forwarded-proto": "https",
|
||||
"x-forwarded-host": "kyoo.example.com",
|
||||
},
|
||||
}),
|
||||
);
|
||||
const body = await resp.json();
|
||||
|
||||
expectStatus(resp, body).toBe(200);
|
||||
expect(body).toMatchObject({
|
||||
items: expect.any(Array),
|
||||
this: "https://kyoo.example.com/api/movies?limit=2",
|
||||
next: expect.stringContaining(
|
||||
"https://kyoo.example.com/api/movies?limit=2",
|
||||
),
|
||||
});
|
||||
});
|
||||
|
||||
it("Second page of pagination respects X-Forwarded headers", async () => {
|
||||
let resp = await handlers.handle(
|
||||
new Request("http://localhost/api/movies?limit=2", {
|
||||
headers: {
|
||||
...(await getJwtHeaders()),
|
||||
"x-forwarded-proto": "https",
|
||||
"x-forwarded-host": "kyoo.example.com",
|
||||
},
|
||||
}),
|
||||
);
|
||||
let body = await resp.json();
|
||||
|
||||
expectStatus(resp, body).toBe(200);
|
||||
expect(body.next).toBeTruthy();
|
||||
expect(body.next).toContain("https://kyoo.example.com");
|
||||
|
||||
// Follow the next link with the same headers
|
||||
resp = await handlers.handle(
|
||||
new Request(body.next, {
|
||||
headers: {
|
||||
...(await getJwtHeaders()),
|
||||
"x-forwarded-proto": "https",
|
||||
"x-forwarded-host": "kyoo.example.com",
|
||||
},
|
||||
}),
|
||||
);
|
||||
body = await resp.json();
|
||||
|
||||
expectStatus(resp, body).toBe(200);
|
||||
expect(body.this).toContain("https://kyoo.example.com");
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user