forked from StrafesNET/maps-service
API_HOST changes, thumbnail fix & cache, "list is empty" fix
API_HOST was replaced in order for thumbnail/any redirects to work properly, this also assumes the API will be at `{BASE_URL}/api`, assuming the reverse proxy causes issues with the way redirects were initially setup to work.
Also no more "Submissions list is empty." while it's loading.
This commit is contained in:
@@ -26,10 +26,10 @@ Prerequisite: golang installed
|
||||
|
||||
Prerequisite: bun installed
|
||||
|
||||
The environment variables `API_HOST` and `AUTH_HOST` will need to be set for the middleware.
|
||||
The environment variables `BASE_URL` and `AUTH_HOST` will need to be set for the middleware.
|
||||
Example `.env` in web's root:
|
||||
```
|
||||
API_HOST="http://localhost:8082/v1/"
|
||||
BASE_URL="http://localhost:8082/"
|
||||
AUTH_HOST="http://localhost:8083/"
|
||||
```
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import "./(styles)/page.scss";
|
||||
import { ListSortConstants } from "../ts/Sort";
|
||||
|
||||
export default function MapfixInfoPage() {
|
||||
const [mapfixes, setMapfixes] = useState<MapfixList>({Total:0,Mapfixes:[]})
|
||||
const [mapfixes, setMapfixes] = useState<MapfixList>({Total:-1,Mapfixes:[]})
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const cardsPerPage = 24; // built to fit on a 1920x1080 monitor
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function MapfixInfoPage() {
|
||||
}, 50);
|
||||
}, [currentPage])
|
||||
|
||||
if (!mapfixes) {
|
||||
if (mapfixes.Total < 0) {
|
||||
return <Webpage>
|
||||
<main>
|
||||
Loading...
|
||||
@@ -55,7 +55,7 @@ export default function MapfixInfoPage() {
|
||||
</Webpage>
|
||||
}
|
||||
|
||||
if (mapfixes && mapfixes.Total == 0) {
|
||||
if (mapfixes.Total == 0) {
|
||||
return <Webpage>
|
||||
<main>
|
||||
Mapfixes list is empty.
|
||||
|
||||
@@ -9,7 +9,7 @@ import "./(styles)/page.scss";
|
||||
import { ListSortConstants } from "../ts/Sort";
|
||||
|
||||
export default function SubmissionInfoPage() {
|
||||
const [submissions, setSubmissions] = useState<SubmissionList>({Total:0,Submissions:[]})
|
||||
const [submissions, setSubmissions] = useState<SubmissionList>({Total:-1,Submissions:[]})
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const cardsPerPage = 24; // built to fit on a 1920x1080 monitor
|
||||
|
||||
@@ -45,7 +45,7 @@ export default function SubmissionInfoPage() {
|
||||
}, 50);
|
||||
}, [currentPage])
|
||||
|
||||
if (!submissions) {
|
||||
if (submissions.Total < 0) {
|
||||
return <Webpage>
|
||||
<main>
|
||||
Loading...
|
||||
@@ -53,7 +53,7 @@ export default function SubmissionInfoPage() {
|
||||
</Webpage>
|
||||
}
|
||||
|
||||
if (submissions && submissions.Total == 0) {
|
||||
if (submissions.Total == 0) {
|
||||
return <Webpage>
|
||||
<main>
|
||||
Submissions list is empty.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
const cache = new Map<number, { buffer: Buffer; expires: number }>();
|
||||
const CACHE_TTL = 15 * 60 * 1000;
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
context: { params: Promise<{ assetId: number }> }
|
||||
@@ -27,6 +30,19 @@ export async function GET(
|
||||
}
|
||||
} catch { }
|
||||
|
||||
const now = Date.now();
|
||||
const cached = cache.get(finalAssetId);
|
||||
|
||||
if (cached && cached.expires > now) {
|
||||
return new NextResponse(cached.buffer, {
|
||||
headers: {
|
||||
'Content-Type': 'image/png',
|
||||
'Content-Length': cached.buffer.length.toString(),
|
||||
'Cache-Control': `public, max-age=${CACHE_TTL / 1000}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://thumbnails.roblox.com/v1/assets?format=png&size=512x512&assetIds=${finalAssetId}`
|
||||
@@ -54,10 +70,13 @@ export async function GET(
|
||||
const arrayBuffer = await imageResponse.arrayBuffer();
|
||||
const buffer = Buffer.from(arrayBuffer);
|
||||
|
||||
cache.set(finalAssetId, { buffer, expires: now + CACHE_TTL });
|
||||
|
||||
return new NextResponse(buffer, {
|
||||
headers: {
|
||||
'Content-Type': 'image/png',
|
||||
'Content-Length': buffer.length.toString(),
|
||||
'Cache-Control': `public, max-age=${CACHE_TTL / 1000}`,
|
||||
},
|
||||
});
|
||||
} catch {
|
||||
|
||||
@@ -5,9 +5,12 @@ export async function GET(
|
||||
context: { params: Promise<{ mapId: string }> }
|
||||
): Promise<NextResponse> {
|
||||
// TODO: implement this, we need a cdn for in-game map thumbnails...
|
||||
|
||||
|
||||
const { mapId } = await context.params;
|
||||
const baseUrl = request.nextUrl.origin; // Gets the current base URL
|
||||
|
||||
return NextResponse.redirect(`${baseUrl}/thumbnails/asset/${mapId}`);
|
||||
const protocol = request.headers.get("x-forwarded-proto") || "https";
|
||||
const host = request.headers.get("host");
|
||||
const origin = `${protocol}://${host}`;
|
||||
|
||||
return NextResponse.redirect(`${origin}/thumbnails/asset/${mapId}`);
|
||||
}
|
||||
@@ -1,29 +1,32 @@
|
||||
import { NextRequest, NextResponse } from "next/server"
|
||||
|
||||
export const config = {
|
||||
matcher: ["/api/:path*", "/auth/:path*"],
|
||||
matcher: ["/api/:path*", "/auth/:path*"],
|
||||
}
|
||||
|
||||
export function middleware(request: NextRequest) {
|
||||
const { pathname, search } = request.nextUrl
|
||||
const { pathname, search } = request.nextUrl
|
||||
|
||||
if (pathname.startsWith("/api")) {
|
||||
if (!process.env.API_HOST) {
|
||||
throw new Error('env variable "API_HOST" is not set')
|
||||
}
|
||||
const apiUrl = new URL(process.env.API_HOST + pathname.replace(/^\/api/, '') + search)
|
||||
return NextResponse.rewrite(apiUrl, { request })
|
||||
} else if (pathname.startsWith("/auth")) {
|
||||
if (pathname.startsWith("/api")) {
|
||||
if (!process.env.BASE_URL) {
|
||||
throw new Error('env variable "BASE_URL" is not set')
|
||||
}
|
||||
|
||||
const baseUrl = process.env.BASE_URL.replace(/\/$/, "");
|
||||
const apiUrl = new URL(baseUrl + pathname + search);
|
||||
|
||||
return NextResponse.rewrite(apiUrl, { request });
|
||||
} else if (pathname.startsWith("/auth")) {
|
||||
if (!process.env.AUTH_HOST) {
|
||||
throw new Error('env variable "AUTH_HOST" is not set')
|
||||
}
|
||||
|
||||
const authHost = process.env.AUTH_HOST.replace(/\/$/, "")
|
||||
const path = pathname.replace(/^\/auth/, "")
|
||||
const redirectUrl = new URL(authHost + path + search)
|
||||
|
||||
return NextResponse.redirect(redirectUrl, 302)
|
||||
}
|
||||
|
||||
const authHost = process.env.AUTH_HOST.replace(/\/$/, "");
|
||||
const path = pathname.replace(/^\/auth/, "");
|
||||
const redirectUrl = new URL(authHost + path + search);
|
||||
|
||||
return NextResponse.next()
|
||||
return NextResponse.redirect(redirectUrl, 302);
|
||||
}
|
||||
|
||||
return NextResponse.next()
|
||||
}
|
||||
Reference in New Issue
Block a user