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 ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub },
|
jwt: { sub },
|
||||||
status,
|
status,
|
||||||
@ -294,7 +294,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
userId: sub,
|
userId: sub,
|
||||||
})) as Entry[];
|
})) as Entry[];
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get entries of a serie" },
|
detail: { description: "Get entries of a serie" },
|
||||||
@ -338,6 +338,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
headers,
|
||||||
jwt: { sub },
|
jwt: { sub },
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
@ -373,7 +374,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
userId: sub,
|
userId: sub,
|
||||||
})) as Extra[];
|
})) as Extra[];
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get extras of a serie" },
|
detail: { description: "Get extras of a serie" },
|
||||||
@ -410,6 +411,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, filter },
|
query: { limit, after, query, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
headers,
|
||||||
jwt: { sub },
|
jwt: { sub },
|
||||||
}) => {
|
}) => {
|
||||||
const sort = newsSort;
|
const sort = newsSort;
|
||||||
@ -427,7 +429,7 @@ export const entriesH = new Elysia({ tags: ["series"] })
|
|||||||
userId: sub,
|
userId: sub,
|
||||||
})) as Entry[];
|
})) as Entry[];
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get new movies/episodes added recently." },
|
detail: { description: "Get new movies/episodes added recently." },
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
"/profiles/me/history",
|
"/profiles/me/history",
|
||||||
async ({
|
async ({
|
||||||
query: { sort, filter, query, limit, after },
|
query: { sort, filter, query, limit, after },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub },
|
jwt: { sub },
|
||||||
}) => {
|
}) => {
|
||||||
@ -87,7 +87,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
progressQ: historyProgressQ,
|
progressQ: historyProgressQ,
|
||||||
})) as Entry[];
|
})) as Entry[];
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
@ -109,7 +109,11 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { sort, filter, query, limit, after },
|
query: { sort, filter, query, limit, after },
|
||||||
headers: { "accept-language": languages, authorization },
|
headers: {
|
||||||
|
"accept-language": languages,
|
||||||
|
authorization,
|
||||||
|
...headers
|
||||||
|
},
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
@ -132,7 +136,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
|
|||||||
progressQ: historyProgressQ,
|
progressQ: historyProgressQ,
|
||||||
})) as Entry[];
|
})) as Entry[];
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
|||||||
"/profiles/me/nextup",
|
"/profiles/me/nextup",
|
||||||
async ({
|
async ({
|
||||||
query: { sort, filter, query, limit, after },
|
query: { sort, filter, query, limit, after },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub },
|
jwt: { sub },
|
||||||
}) => {
|
}) => {
|
||||||
@ -124,7 +124,7 @@ export const nextup = new Elysia({ tags: ["profiles"] })
|
|||||||
.limit(limit)
|
.limit(limit)
|
||||||
.execute({ userId: sub });
|
.execute({ userId: sub });
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
|
|||||||
@ -142,7 +142,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
"/profiles/me/watchlist",
|
"/profiles/me/watchlist",
|
||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
}) => {
|
}) => {
|
||||||
@ -162,7 +162,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
relations: ["nextEntry"],
|
relations: ["nextEntry"],
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all movies/series in your watchlist" },
|
detail: { description: "Get all movies/series in your watchlist" },
|
||||||
@ -195,7 +195,11 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
jwt: { settings },
|
jwt: { settings },
|
||||||
headers: { "accept-language": languages, authorization },
|
headers: {
|
||||||
|
"accept-language": languages,
|
||||||
|
authorization,
|
||||||
|
...headers
|
||||||
|
},
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
@ -218,7 +222,7 @@ export const watchlistH = new Elysia({ tags: ["profiles"] })
|
|||||||
relations: ["nextEntry"],
|
relations: ["nextEntry"],
|
||||||
userId: uInfo.id,
|
userId: uInfo.id,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export const seasonsH = new Elysia({ tags: ["series"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
@ -110,7 +110,7 @@ export const seasonsH = new Elysia({ tags: ["series"] })
|
|||||||
)
|
)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
|
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get seasons of a serie" },
|
detail: { description: "Get seasons of a serie" },
|
||||||
|
|||||||
@ -143,7 +143,7 @@ export const collections = new Elysia({
|
|||||||
"",
|
"",
|
||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
}) => {
|
}) => {
|
||||||
@ -158,7 +158,7 @@ export const collections = new Elysia({
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all collections" },
|
detail: { description: "Get all collections" },
|
||||||
@ -227,7 +227,7 @@ export const collections = new Elysia({
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -265,7 +265,7 @@ export const collections = new Elysia({
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all movies in a collection" },
|
detail: { description: "Get all movies in a collection" },
|
||||||
@ -284,7 +284,7 @@ export const collections = new Elysia({
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -322,7 +322,7 @@ export const collections = new Elysia({
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all series in a collection" },
|
detail: { description: "Get all series in a collection" },
|
||||||
@ -341,7 +341,7 @@ export const collections = new Elysia({
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -375,7 +375,7 @@ export const collections = new Elysia({
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all series & movies in a collection" },
|
detail: { description: "Get all series & movies in a collection" },
|
||||||
|
|||||||
@ -133,7 +133,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
|
|||||||
"",
|
"",
|
||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
}) => {
|
}) => {
|
||||||
@ -148,7 +148,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all movies" },
|
detail: { description: "Get all movies" },
|
||||||
|
|||||||
@ -136,7 +136,7 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
|
|||||||
"",
|
"",
|
||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
}) => {
|
}) => {
|
||||||
@ -151,7 +151,7 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all series" },
|
detail: { description: "Get all series" },
|
||||||
|
|||||||
@ -63,7 +63,7 @@ export const showsH = new Elysia({ prefix: "/shows", tags: ["shows"] })
|
|||||||
preferOriginal,
|
preferOriginal,
|
||||||
ignoreInCollection,
|
ignoreInCollection,
|
||||||
},
|
},
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
}) => {
|
}) => {
|
||||||
@ -81,7 +81,7 @@ export const showsH = new Elysia({ prefix: "/shows", tags: ["shows"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all movies/series/collections" },
|
detail: { description: "Get all movies/series/collections" },
|
||||||
|
|||||||
@ -189,7 +189,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
status,
|
status,
|
||||||
@ -269,7 +269,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
roles.showPk,
|
roles.showPk,
|
||||||
)
|
)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
@ -316,7 +316,11 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
"/staff",
|
"/staff",
|
||||||
async ({ query: { limit, after, sort, query }, request: { url } }) => {
|
async ({
|
||||||
|
query: { limit, after, sort, query },
|
||||||
|
request: { url },
|
||||||
|
headers,
|
||||||
|
}) => {
|
||||||
const items = await db
|
const items = await db
|
||||||
.select()
|
.select()
|
||||||
.from(staff)
|
.from(staff)
|
||||||
@ -333,7 +337,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
staff.pk,
|
staff.pk,
|
||||||
)
|
)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
@ -362,6 +366,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
headers,
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
const [movie] = await db
|
const [movie] = await db
|
||||||
@ -389,7 +394,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
sort,
|
sort,
|
||||||
filter: and(eq(roles.showPk, movie.pk), filter),
|
filter: and(eq(roles.showPk, movie.pk), filter),
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
@ -429,6 +434,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter },
|
query: { limit, after, query, sort, filter },
|
||||||
request: { url },
|
request: { url },
|
||||||
|
headers,
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
const [serie] = await db
|
const [serie] = await db
|
||||||
@ -456,7 +462,7 @@ export const staffH = new Elysia({ tags: ["staff"] })
|
|||||||
sort,
|
sort,
|
||||||
filter: and(eq(roles.showPk, serie.pk), filter),
|
filter: and(eq(roles.showPk, serie.pk), filter),
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: {
|
detail: {
|
||||||
|
|||||||
@ -228,7 +228,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
"",
|
"",
|
||||||
async ({
|
async ({
|
||||||
query: { limit, after, query, sort },
|
query: { limit, after, query, sort },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
request: { url },
|
request: { url },
|
||||||
}) => {
|
}) => {
|
||||||
const langs = processLanguages(languages);
|
const langs = processLanguages(languages);
|
||||||
@ -239,7 +239,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
sort,
|
sort,
|
||||||
languages: langs,
|
languages: langs,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all studios" },
|
detail: { description: "Get all studios" },
|
||||||
@ -302,7 +302,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -344,7 +344,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
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." },
|
detail: { description: "Get all series & movies made by a studio." },
|
||||||
@ -363,7 +363,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -406,7 +406,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all movies made by a studio." },
|
detail: { description: "Get all movies made by a studio." },
|
||||||
@ -425,7 +425,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
async ({
|
async ({
|
||||||
params: { id },
|
params: { id },
|
||||||
query: { limit, after, query, sort, filter, preferOriginal },
|
query: { limit, after, query, sort, filter, preferOriginal },
|
||||||
headers: { "accept-language": languages },
|
headers: { "accept-language": languages, ...headers },
|
||||||
jwt: { sub, settings },
|
jwt: { sub, settings },
|
||||||
request: { url },
|
request: { url },
|
||||||
status,
|
status,
|
||||||
@ -468,7 +468,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
|||||||
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
preferOriginal: preferOriginal ?? settings.preferOriginal,
|
||||||
userId: sub,
|
userId: sub,
|
||||||
});
|
});
|
||||||
return createPage(items, { url, sort, limit });
|
return createPage(items, { url, sort, limit, headers });
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
detail: { description: "Get all series made by a studio." },
|
detail: { description: "Get all series made by a studio." },
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import type { ObjectOptions } from "@sinclair/typebox";
|
import type { ObjectOptions } from "@sinclair/typebox";
|
||||||
import { type TSchema, t } from "elysia";
|
import { type TSchema, t } from "elysia";
|
||||||
|
import { buildUrl } from "~/utils";
|
||||||
import { generateAfter } from "./keyset-paginate";
|
import { generateAfter } from "./keyset-paginate";
|
||||||
import type { Sort } from "./sort";
|
import type { Sort } from "./sort";
|
||||||
|
|
||||||
@ -18,11 +19,31 @@ export const Page = <T extends TSchema>(schema: T, options?: ObjectOptions) =>
|
|||||||
|
|
||||||
export const createPage = <T>(
|
export const createPage = <T>(
|
||||||
items: 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 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) {
|
if (sort.random) {
|
||||||
uri.searchParams.set("sort", `random:${sort.random.seed}`);
|
uri.searchParams.set("sort", `random:${sort.random.seed}`);
|
||||||
url = uri.toString();
|
url = uri.toString();
|
||||||
@ -35,5 +56,5 @@ export const createPage = <T>(
|
|||||||
uri.searchParams.set("after", generateAfter(items[items.length - 1], sort));
|
uri.searchParams.set("after", generateAfter(items[items.length - 1], sort));
|
||||||
next = uri.toString();
|
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