mirror of
https://github.com/direct-img/direct-img.link.git
synced 2026-10-08 22:45:19 +00:00
Perf: Serve homepage and assets without invoking Functions
Add _routes.json so /, /robots.txt and /assets/* skip the worker and don't count against the Functions request quota. rate-limit.js moves to assets/ so the homepage reads it client-side instead of via HTMLRewriter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"include": ["/*"],
|
||||||
|
"exclude": ["/", "/index.html", "/robots.txt", "/assets/*"]
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
// New searches (cache misses) allowed per IP per day, reset at 00:00 UTC. Cache hits never count.
|
// New searches (cache misses) allowed per IP per day, reset at 00:00 UTC. Cache hits never count.
|
||||||
// Safe to edit by hand. The homepage reads these automatically; README.md needs a manual update.
|
// Safe to edit by hand. Imported by the worker and by the homepage (as a static file, so no Functions quota);
|
||||||
|
// README.md needs a manual update.
|
||||||
// The burst limit (~10 req/10s) is a Cloudflare WAF rule, not set here.
|
// The burst limit (~10 req/10s) is a Cloudflare WAF rule, not set here.
|
||||||
export const DAILY_LIMIT = 35;
|
export const DAILY_LIMIT = 35;
|
||||||
export const FREE_DAILY_LIMIT = 100;
|
export const FREE_DAILY_LIMIT = 100;
|
||||||
+3
-17
@@ -2,7 +2,7 @@ import { braveImageSearch } from "./_utils/brave.js";
|
|||||||
import { bingImageSearchFallback } from "./_utils/bing.js";
|
import { bingImageSearchFallback } from "./_utils/bing.js";
|
||||||
import { freeImageUrls, parseFreeSource, FREE_UA } from "./_utils/free.js";
|
import { freeImageUrls, parseFreeSource, FREE_UA } from "./_utils/free.js";
|
||||||
import { isFlickrPlaceholder } from "./_utils/flickr.js";
|
import { isFlickrPlaceholder } from "./_utils/flickr.js";
|
||||||
import * as LIMITS from "./_utils/rate-limit.js";
|
import * as LIMITS from "../assets/rate-limit.js";
|
||||||
|
|
||||||
const TTL_SECONDS = 90 * 24 * 60 * 60;
|
const TTL_SECONDS = 90 * 24 * 60 * 60;
|
||||||
const MAX_INDEX = 20;
|
const MAX_INDEX = 20;
|
||||||
@@ -13,8 +13,8 @@ export async function onRequest(context) {
|
|||||||
const path = params.path?.join("/") || "";
|
const path = params.path?.join("/") || "";
|
||||||
const asset = f => env.ASSETS.fetch(new Request(new URL(`/assets/${f}`, url.origin)));
|
const asset = f => env.ASSETS.fetch(new Request(new URL(`/assets/${f}`, url.origin)));
|
||||||
|
|
||||||
if (!path || path === "index.html") return homepage(env, url);
|
// _routes.json serves these statically without invoking this function; kept as a fallback
|
||||||
if (path === "robots.txt" || path.startsWith("assets/")) {
|
if (!path || path === "index.html" || path === "robots.txt" || path.startsWith("assets/")) {
|
||||||
return env.ASSETS.fetch(request);
|
return env.ASSETS.fetch(request);
|
||||||
}
|
}
|
||||||
if (path === "favicon.ico") return asset("favicon.ico");
|
if (path === "favicon.ico") return asset("favicon.ico");
|
||||||
@@ -207,20 +207,6 @@ async function* webImageUrls(context, query) {
|
|||||||
yield* (await bingImageSearchFallback(query)) || [];
|
yield* (await bingImageSearchFallback(query)) || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fills each <span data-limit="NAME"> with that export of rate-limit.js, so the page never shows stale limits.
|
|
||||||
// Fetched without the browser's If-None-Match and served without an ETag, so a cached copy can't either.
|
|
||||||
async function homepage(env, url) {
|
|
||||||
const res = await env.ASSETS.fetch(new Request(url));
|
|
||||||
const headers = new Headers(res.headers);
|
|
||||||
headers.delete("etag");
|
|
||||||
return new HTMLRewriter().on("[data-limit]", {
|
|
||||||
element: e => {
|
|
||||||
const v = LIMITS[e.getAttribute("data-limit")];
|
|
||||||
if (v != null) e.setInnerContent(`${v}`);
|
|
||||||
}
|
|
||||||
}).transform(new Response(res.body, { status: res.status, headers }));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setupSurreal(env) {
|
async function setupSurreal(env) {
|
||||||
if (!env.SURREAL_URL || !env.SURREAL_USER || !env.SURREAL_PASS) return jsonResponse(500, { error: "SurrealDB env vars missing" });
|
if (!env.SURREAL_URL || !env.SURREAL_USER || !env.SURREAL_PASS) return jsonResponse(500, { error: "SurrealDB env vars missing" });
|
||||||
const sql = `DEFINE NAMESPACE IF NOT EXISTS direct_img;
|
const sql = `DEFINE NAMESPACE IF NOT EXISTS direct_img;
|
||||||
|
|||||||
@@ -127,5 +127,9 @@ Use images to complement your responses, powered by Brave.</code></pre>
|
|||||||
},()=>getSelection().selectAllChildren(p));
|
},()=>getSelection().selectAllChildren(p));
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
import * as L from '/assets/rate-limit.js';
|
||||||
|
for(const e of document.querySelectorAll('[data-limit]'))e.textContent=L[e.dataset.limit]??e.textContent;
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user