refactor(functions): 重构静态资源处理逻辑,使用getAssetFromKV和ASSETS API
优化静态资源处理逻辑,移除自定义的handleStaticAssets函数,改用Cloudflare的getAssetFromKV和ASSETS API 添加对SPA路由的支持,当资源不存在时返回index.html 更新依赖并清理不再使用的代码
This commit is contained in:
Binary file not shown.
@@ -3,12 +3,12 @@
|
|||||||
// export dynamically through wrangler, or we can potentially let users directly
|
// export dynamically through wrangler, or we can potentially let users directly
|
||||||
// add them as a sort of "plugin" system.
|
// add them as a sort of "plugin" system.
|
||||||
|
|
||||||
import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-xddOtL\\middleware-insertion-facade.js";
|
import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-DanHCD\\middleware-insertion-facade.js";
|
||||||
import { __facade_invoke__, __facade_register__, Dispatcher } from "D:\\github\\pixivnow\\node_modules\\.pnpm\\wrangler@4.42.1\\node_modules\\wrangler\\templates\\middleware\\common.ts";
|
import { __facade_invoke__, __facade_register__, Dispatcher } from "D:\\github\\pixivnow\\node_modules\\.pnpm\\wrangler@4.42.1\\node_modules\\wrangler\\templates\\middleware\\common.ts";
|
||||||
import type { WorkerEntrypointConstructor } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-xddOtL\\middleware-insertion-facade.js";
|
import type { WorkerEntrypointConstructor } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-DanHCD\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
// Preserve all the exports from the worker
|
// Preserve all the exports from the worker
|
||||||
export * from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-xddOtL\\middleware-insertion-facade.js";
|
export * from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-DanHCD\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
class __Facade_ScheduledController__ implements ScheduledController {
|
class __Facade_ScheduledController__ implements ScheduledController {
|
||||||
readonly #noRetry: ScheduledController["noRetry"];
|
readonly #noRetry: ScheduledController["noRetry"];
|
||||||
30
.wrangler/tmp/bundle-RM404r/checked-fetch.js
Normal file
30
.wrangler/tmp/bundle-RM404r/checked-fetch.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const urls = new Set();
|
||||||
|
|
||||||
|
function checkURL(request, init) {
|
||||||
|
const url =
|
||||||
|
request instanceof URL
|
||||||
|
? request
|
||||||
|
: new URL(
|
||||||
|
(typeof request === "string"
|
||||||
|
? new Request(request, init)
|
||||||
|
: request
|
||||||
|
).url
|
||||||
|
);
|
||||||
|
if (url.port && url.port !== "443" && url.protocol === "https:") {
|
||||||
|
if (!urls.has(url.toString())) {
|
||||||
|
urls.add(url.toString());
|
||||||
|
console.warn(
|
||||||
|
`WARNING: known issue with \`fetch()\` requests to custom HTTPS ports in published Workers:\n` +
|
||||||
|
` - ${url.toString()} - the custom port will be ignored when the Worker is published using the \`wrangler deploy\` command.\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis.fetch = new Proxy(globalThis.fetch, {
|
||||||
|
apply(target, thisArg, argArray) {
|
||||||
|
const [request, init] = argArray;
|
||||||
|
checkURL(request, init);
|
||||||
|
return Reflect.apply(target, thisArg, argArray);
|
||||||
|
},
|
||||||
|
});
|
||||||
12
.wrangler/tmp/bundle-RM404r/middleware-insertion-facade.js
Normal file
12
.wrangler/tmp/bundle-RM404r/middleware-insertion-facade.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import worker, * as OTHER_EXPORTS from "D:\\github\\pixivnow\\functions\\[[path]].ts";
|
||||||
|
import * as __MIDDLEWARE_0__ from "C:\\Users\\15765\\AppData\\Roaming\\npm\\node_modules\\wrangler\\templates\\middleware\\middleware-ensure-req-body-drained.ts";
|
||||||
|
import * as __MIDDLEWARE_1__ from "C:\\Users\\15765\\AppData\\Roaming\\npm\\node_modules\\wrangler\\templates\\middleware\\middleware-miniflare3-json-error.ts";
|
||||||
|
import * as __MIDDLEWARE_2__ from "C:\\Users\\15765\\AppData\\Roaming\\npm\\node_modules\\wrangler\\templates\\middleware\\middleware-serve-static-assets.ts";
|
||||||
|
|
||||||
|
export * from "D:\\github\\pixivnow\\functions\\[[path]].ts";
|
||||||
|
|
||||||
|
export const __INTERNAL_WRANGLER_MIDDLEWARE__ = [
|
||||||
|
...(OTHER_EXPORTS.__INJECT_FOR_TESTING_WRANGLER_MIDDLEWARE__ ?? []),
|
||||||
|
__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default,__MIDDLEWARE_2__.default
|
||||||
|
]
|
||||||
|
export default worker;
|
||||||
134
.wrangler/tmp/bundle-RM404r/middleware-loader.entry.ts
Normal file
134
.wrangler/tmp/bundle-RM404r/middleware-loader.entry.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
// This loads all middlewares exposed on the middleware object and then starts
|
||||||
|
// the invocation chain. The big idea is that we can add these to the middleware
|
||||||
|
// export dynamically through wrangler, or we can potentially let users directly
|
||||||
|
// add them as a sort of "plugin" system.
|
||||||
|
|
||||||
|
import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-RM404r\\middleware-insertion-facade.js";
|
||||||
|
import { __facade_invoke__, __facade_register__, Dispatcher } from "C:\\Users\\15765\\AppData\\Roaming\\npm\\node_modules\\wrangler\\templates\\middleware\\common.ts";
|
||||||
|
import type { WorkerEntrypointConstructor } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-RM404r\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
|
// Preserve all the exports from the worker
|
||||||
|
export * from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-RM404r\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
|
class __Facade_ScheduledController__ implements ScheduledController {
|
||||||
|
readonly #noRetry: ScheduledController["noRetry"];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly scheduledTime: number,
|
||||||
|
readonly cron: string,
|
||||||
|
noRetry: ScheduledController["noRetry"]
|
||||||
|
) {
|
||||||
|
this.#noRetry = noRetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
noRetry() {
|
||||||
|
if (!(this instanceof __Facade_ScheduledController__)) {
|
||||||
|
throw new TypeError("Illegal invocation");
|
||||||
|
}
|
||||||
|
// Need to call native method immediately in case uncaught error thrown
|
||||||
|
this.#noRetry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapExportedHandler(worker: ExportedHandler): ExportedHandler {
|
||||||
|
// If we don't have any middleware defined, just return the handler as is
|
||||||
|
if (
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
|
||||||
|
) {
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
// Otherwise, register all middleware once
|
||||||
|
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
||||||
|
__facade_register__(middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDispatcher: ExportedHandlerFetchHandler = function (
|
||||||
|
request,
|
||||||
|
env,
|
||||||
|
ctx
|
||||||
|
) {
|
||||||
|
if (worker.fetch === undefined) {
|
||||||
|
throw new Error("Handler does not export a fetch() function.");
|
||||||
|
}
|
||||||
|
return worker.fetch(request, env, ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...worker,
|
||||||
|
fetch(request, env, ctx) {
|
||||||
|
const dispatcher: Dispatcher = function (type, init) {
|
||||||
|
if (type === "scheduled" && worker.scheduled !== undefined) {
|
||||||
|
const controller = new __Facade_ScheduledController__(
|
||||||
|
Date.now(),
|
||||||
|
init.cron ?? "",
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
return worker.scheduled(controller, env, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapWorkerEntrypoint(
|
||||||
|
klass: WorkerEntrypointConstructor
|
||||||
|
): WorkerEntrypointConstructor {
|
||||||
|
// If we don't have any middleware defined, just return the handler as is
|
||||||
|
if (
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
|
||||||
|
) {
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
// Otherwise, register all middleware once
|
||||||
|
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
||||||
|
__facade_register__(middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `extend`ing `klass` here so other RPC methods remain callable
|
||||||
|
return class extends klass {
|
||||||
|
#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (
|
||||||
|
request,
|
||||||
|
env,
|
||||||
|
ctx
|
||||||
|
) => {
|
||||||
|
this.env = env;
|
||||||
|
this.ctx = ctx;
|
||||||
|
if (super.fetch === undefined) {
|
||||||
|
throw new Error("Entrypoint class does not define a fetch() function.");
|
||||||
|
}
|
||||||
|
return super.fetch(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
#dispatcher: Dispatcher = (type, init) => {
|
||||||
|
if (type === "scheduled" && super.scheduled !== undefined) {
|
||||||
|
const controller = new __Facade_ScheduledController__(
|
||||||
|
Date.now(),
|
||||||
|
init.cron ?? "",
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
return super.scheduled(controller);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch(request: Request<unknown, IncomingRequestCfProperties>) {
|
||||||
|
return __facade_invoke__(
|
||||||
|
request,
|
||||||
|
this.env,
|
||||||
|
this.ctx,
|
||||||
|
this.#dispatcher,
|
||||||
|
this.#fetchDispatcher
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;
|
||||||
|
if (typeof ENTRY === "object") {
|
||||||
|
WRAPPED_ENTRY = wrapExportedHandler(ENTRY);
|
||||||
|
} else if (typeof ENTRY === "function") {
|
||||||
|
WRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);
|
||||||
|
}
|
||||||
|
export default WRAPPED_ENTRY;
|
||||||
30
.wrangler/tmp/bundle-z3POAk/checked-fetch.js
Normal file
30
.wrangler/tmp/bundle-z3POAk/checked-fetch.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const urls = new Set();
|
||||||
|
|
||||||
|
function checkURL(request, init) {
|
||||||
|
const url =
|
||||||
|
request instanceof URL
|
||||||
|
? request
|
||||||
|
: new URL(
|
||||||
|
(typeof request === "string"
|
||||||
|
? new Request(request, init)
|
||||||
|
: request
|
||||||
|
).url
|
||||||
|
);
|
||||||
|
if (url.port && url.port !== "443" && url.protocol === "https:") {
|
||||||
|
if (!urls.has(url.toString())) {
|
||||||
|
urls.add(url.toString());
|
||||||
|
console.warn(
|
||||||
|
`WARNING: known issue with \`fetch()\` requests to custom HTTPS ports in published Workers:\n` +
|
||||||
|
` - ${url.toString()} - the custom port will be ignored when the Worker is published using the \`wrangler deploy\` command.\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalThis.fetch = new Proxy(globalThis.fetch, {
|
||||||
|
apply(target, thisArg, argArray) {
|
||||||
|
const [request, init] = argArray;
|
||||||
|
checkURL(request, init);
|
||||||
|
return Reflect.apply(target, thisArg, argArray);
|
||||||
|
},
|
||||||
|
});
|
||||||
11
.wrangler/tmp/bundle-z3POAk/middleware-insertion-facade.js
Normal file
11
.wrangler/tmp/bundle-z3POAk/middleware-insertion-facade.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import worker, * as OTHER_EXPORTS from "D:\\github\\pixivnow\\functions\\[[path]].ts";
|
||||||
|
import * as __MIDDLEWARE_0__ from "D:\\github\\pixivnow\\node_modules\\.pnpm\\wrangler@4.42.1\\node_modules\\wrangler\\templates\\middleware\\middleware-ensure-req-body-drained.ts";
|
||||||
|
import * as __MIDDLEWARE_1__ from "D:\\github\\pixivnow\\node_modules\\.pnpm\\wrangler@4.42.1\\node_modules\\wrangler\\templates\\middleware\\middleware-miniflare3-json-error.ts";
|
||||||
|
|
||||||
|
export * from "D:\\github\\pixivnow\\functions\\[[path]].ts";
|
||||||
|
const MIDDLEWARE_TEST_INJECT = "__INJECT_FOR_TESTING_WRANGLER_MIDDLEWARE__";
|
||||||
|
export const __INTERNAL_WRANGLER_MIDDLEWARE__ = [
|
||||||
|
|
||||||
|
__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default
|
||||||
|
]
|
||||||
|
export default worker;
|
||||||
134
.wrangler/tmp/bundle-z3POAk/middleware-loader.entry.ts
Normal file
134
.wrangler/tmp/bundle-z3POAk/middleware-loader.entry.ts
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
// This loads all middlewares exposed on the middleware object and then starts
|
||||||
|
// the invocation chain. The big idea is that we can add these to the middleware
|
||||||
|
// export dynamically through wrangler, or we can potentially let users directly
|
||||||
|
// add them as a sort of "plugin" system.
|
||||||
|
|
||||||
|
import ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-z3POAk\\middleware-insertion-facade.js";
|
||||||
|
import { __facade_invoke__, __facade_register__, Dispatcher } from "D:\\github\\pixivnow\\node_modules\\.pnpm\\wrangler@4.42.1\\node_modules\\wrangler\\templates\\middleware\\common.ts";
|
||||||
|
import type { WorkerEntrypointConstructor } from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-z3POAk\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
|
// Preserve all the exports from the worker
|
||||||
|
export * from "D:\\github\\pixivnow\\.wrangler\\tmp\\bundle-z3POAk\\middleware-insertion-facade.js";
|
||||||
|
|
||||||
|
class __Facade_ScheduledController__ implements ScheduledController {
|
||||||
|
readonly #noRetry: ScheduledController["noRetry"];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly scheduledTime: number,
|
||||||
|
readonly cron: string,
|
||||||
|
noRetry: ScheduledController["noRetry"]
|
||||||
|
) {
|
||||||
|
this.#noRetry = noRetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
noRetry() {
|
||||||
|
if (!(this instanceof __Facade_ScheduledController__)) {
|
||||||
|
throw new TypeError("Illegal invocation");
|
||||||
|
}
|
||||||
|
// Need to call native method immediately in case uncaught error thrown
|
||||||
|
this.#noRetry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapExportedHandler(worker: ExportedHandler): ExportedHandler {
|
||||||
|
// If we don't have any middleware defined, just return the handler as is
|
||||||
|
if (
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
|
||||||
|
) {
|
||||||
|
return worker;
|
||||||
|
}
|
||||||
|
// Otherwise, register all middleware once
|
||||||
|
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
||||||
|
__facade_register__(middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchDispatcher: ExportedHandlerFetchHandler = function (
|
||||||
|
request,
|
||||||
|
env,
|
||||||
|
ctx
|
||||||
|
) {
|
||||||
|
if (worker.fetch === undefined) {
|
||||||
|
throw new Error("Handler does not export a fetch() function.");
|
||||||
|
}
|
||||||
|
return worker.fetch(request, env, ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...worker,
|
||||||
|
fetch(request, env, ctx) {
|
||||||
|
const dispatcher: Dispatcher = function (type, init) {
|
||||||
|
if (type === "scheduled" && worker.scheduled !== undefined) {
|
||||||
|
const controller = new __Facade_ScheduledController__(
|
||||||
|
Date.now(),
|
||||||
|
init.cron ?? "",
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
return worker.scheduled(controller, env, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapWorkerEntrypoint(
|
||||||
|
klass: WorkerEntrypointConstructor
|
||||||
|
): WorkerEntrypointConstructor {
|
||||||
|
// If we don't have any middleware defined, just return the handler as is
|
||||||
|
if (
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||
|
||||||
|
__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0
|
||||||
|
) {
|
||||||
|
return klass;
|
||||||
|
}
|
||||||
|
// Otherwise, register all middleware once
|
||||||
|
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
||||||
|
__facade_register__(middleware);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `extend`ing `klass` here so other RPC methods remain callable
|
||||||
|
return class extends klass {
|
||||||
|
#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (
|
||||||
|
request,
|
||||||
|
env,
|
||||||
|
ctx
|
||||||
|
) => {
|
||||||
|
this.env = env;
|
||||||
|
this.ctx = ctx;
|
||||||
|
if (super.fetch === undefined) {
|
||||||
|
throw new Error("Entrypoint class does not define a fetch() function.");
|
||||||
|
}
|
||||||
|
return super.fetch(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
#dispatcher: Dispatcher = (type, init) => {
|
||||||
|
if (type === "scheduled" && super.scheduled !== undefined) {
|
||||||
|
const controller = new __Facade_ScheduledController__(
|
||||||
|
Date.now(),
|
||||||
|
init.cron ?? "",
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
return super.scheduled(controller);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch(request: Request<unknown, IncomingRequestCfProperties>) {
|
||||||
|
return __facade_invoke__(
|
||||||
|
request,
|
||||||
|
this.env,
|
||||||
|
this.ctx,
|
||||||
|
this.#dispatcher,
|
||||||
|
this.#fetchDispatcher
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;
|
||||||
|
if (typeof ENTRY === "object") {
|
||||||
|
WRAPPED_ENTRY = wrapExportedHandler(ENTRY);
|
||||||
|
} else if (typeof ENTRY === "function") {
|
||||||
|
WRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);
|
||||||
|
}
|
||||||
|
export default WRAPPED_ENTRY;
|
||||||
1074
.wrangler/tmp/dev-7eqWE0/[[path]].js
Normal file
1074
.wrangler/tmp/dev-7eqWE0/[[path]].js
Normal file
File diff suppressed because one or more lines are too long
8
.wrangler/tmp/dev-7eqWE0/[[path]].js.map
Normal file
8
.wrangler/tmp/dev-7eqWE0/[[path]].js.map
Normal file
File diff suppressed because one or more lines are too long
1074
.wrangler/tmp/dev-C1gQCM/[[path]].js
Normal file
1074
.wrangler/tmp/dev-C1gQCM/[[path]].js
Normal file
File diff suppressed because one or more lines are too long
8
.wrangler/tmp/dev-C1gQCM/[[path]].js.map
Normal file
8
.wrangler/tmp/dev-C1gQCM/[[path]].js.map
Normal file
File diff suppressed because one or more lines are too long
1455
.wrangler/tmp/dev-Iqyccn/[[path]].js
Normal file
1455
.wrangler/tmp/dev-Iqyccn/[[path]].js
Normal file
File diff suppressed because one or more lines are too long
8
.wrangler/tmp/dev-Iqyccn/[[path]].js.map
Normal file
8
.wrangler/tmp/dev-Iqyccn/[[path]].js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -1,624 +0,0 @@
|
|||||||
var __defProp = Object.defineProperty;
|
|
||||||
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
||||||
|
|
||||||
// .wrangler/tmp/bundle-xddOtL/checked-fetch.js
|
|
||||||
var urls = /* @__PURE__ */ new Set();
|
|
||||||
function checkURL(request, init) {
|
|
||||||
const url = request instanceof URL ? request : new URL(
|
|
||||||
(typeof request === "string" ? new Request(request, init) : request).url
|
|
||||||
);
|
|
||||||
if (url.port && url.port !== "443" && url.protocol === "https:") {
|
|
||||||
if (!urls.has(url.toString())) {
|
|
||||||
urls.add(url.toString());
|
|
||||||
console.warn(
|
|
||||||
`WARNING: known issue with \`fetch()\` requests to custom HTTPS ports in published Workers:
|
|
||||||
- ${url.toString()} - the custom port will be ignored when the Worker is published using the \`wrangler deploy\` command.
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__name(checkURL, "checkURL");
|
|
||||||
globalThis.fetch = new Proxy(globalThis.fetch, {
|
|
||||||
apply(target, thisArg, argArray) {
|
|
||||||
const [request, init] = argArray;
|
|
||||||
checkURL(request, init);
|
|
||||||
return Reflect.apply(target, thisArg, argArray);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// functions/[[path]].ts
|
|
||||||
function corsHeaders() {
|
|
||||||
return {
|
|
||||||
"Access-Control-Allow-Origin": "*",
|
|
||||||
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
|
|
||||||
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
|
|
||||||
"Access-Control-Max-Age": "86400"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
__name(corsHeaders, "corsHeaders");
|
|
||||||
function corsResponse(response) {
|
|
||||||
const headers = new Headers(response.headers);
|
|
||||||
Object.entries(corsHeaders()).forEach(([key, value]) => {
|
|
||||||
headers.set(key, value);
|
|
||||||
});
|
|
||||||
return new Response(response.body, {
|
|
||||||
status: response.status,
|
|
||||||
statusText: response.statusText,
|
|
||||||
headers
|
|
||||||
});
|
|
||||||
}
|
|
||||||
__name(corsResponse, "corsResponse");
|
|
||||||
var path_default = {
|
|
||||||
fetch: /* @__PURE__ */ __name(async (request, env, ctx) => {
|
|
||||||
console.log("Worker fetch called:", request.method, request.url);
|
|
||||||
const url = new URL(request.url);
|
|
||||||
const path = url.pathname;
|
|
||||||
if (request.method === "OPTIONS") {
|
|
||||||
return new Response(null, {
|
|
||||||
status: 200,
|
|
||||||
headers: corsHeaders()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (path === "/api/illust/random") {
|
|
||||||
return await handleRandomAPI(request, env, url);
|
|
||||||
}
|
|
||||||
if (path.match(/^\/(ajax|rpc)\//)) {
|
|
||||||
return await handleGenericProxy(request, env);
|
|
||||||
}
|
|
||||||
if (path.match(/^\/[~-]\//)) {
|
|
||||||
return await handleImageProxy(request, env);
|
|
||||||
}
|
|
||||||
if (path === "/api/user") {
|
|
||||||
return await handleUserAPI(request, env, url);
|
|
||||||
}
|
|
||||||
if (path.startsWith("/assets/") || path === "/favicon.ico" || path === "/robots.txt" || path.startsWith("/images/")) {
|
|
||||||
return await handleStaticAssets(request, env, path);
|
|
||||||
}
|
|
||||||
return await handleFrontendPage(request, env);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Worker error:", error);
|
|
||||||
return corsResponse(new Response(JSON.stringify({
|
|
||||||
error: "Internal server error",
|
|
||||||
message: error instanceof Error ? error.message : "Unknown error"
|
|
||||||
}), {
|
|
||||||
status: 500,
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}, "fetch")
|
|
||||||
};
|
|
||||||
async function handleRandomAPI(request, env, url) {
|
|
||||||
try {
|
|
||||||
const requestImage = (request.headers.get("accept")?.includes("image") || url.searchParams.get("format") === "image") && url.searchParams.get("format") !== "json";
|
|
||||||
const mockIllusts = [
|
|
||||||
{
|
|
||||||
id: "123456789",
|
|
||||||
title: "Test Illustration",
|
|
||||||
userId: "987654321",
|
|
||||||
userName: "Test Artist",
|
|
||||||
tags: ["test", "mock"],
|
|
||||||
updateDate: "2024-01-01T12:00:00+00:00",
|
|
||||||
urls: {
|
|
||||||
mini: "https://i.pximg.net/c/48x48/img-master/img/2024/01/01/12/00/00/123456789_p0_square1200.jpg",
|
|
||||||
thumb: "https://i.pximg.net/c/250x250_80_a2/img-master/img/2024/01/01/12/00/00/123456789_p0_square1200.jpg",
|
|
||||||
small: "https://i.pximg.net/c/540x540_70/img-master/img/2024/01/01/12/00/00/123456789_p0_master1200.jpg",
|
|
||||||
regular: "https://i.pximg.net/img-master/img/2024/01/01/12/00/00/123456789_p0_master1200.jpg",
|
|
||||||
original: "https://i.pximg.net/img-original/img/2024/01/01/12/00/00/123456789_p0.jpg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
if (requestImage && mockIllusts[0]?.urls?.regular) {
|
|
||||||
return corsResponse(new Response(null, {
|
|
||||||
status: 302,
|
|
||||||
headers: { Location: mockIllusts[0].urls.regular }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return corsResponse(new Response(JSON.stringify(mockIllusts), {
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in random API:", error);
|
|
||||||
return corsResponse(new Response(JSON.stringify({
|
|
||||||
error: "Internal server error",
|
|
||||||
message: error instanceof Error ? error.message : "Unknown error"
|
|
||||||
}), {
|
|
||||||
status: 500,
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__name(handleRandomAPI, "handleRandomAPI");
|
|
||||||
async function handleGenericProxy(request, env) {
|
|
||||||
const url = new URL(request.url);
|
|
||||||
url.hostname = "www.pixiv.net";
|
|
||||||
const headers = new Headers(request.headers);
|
|
||||||
headers.set("origin", "https://www.pixiv.net");
|
|
||||||
headers.set("referer", "https://www.pixiv.net/");
|
|
||||||
headers.set("user-agent", env.USER_AGENT || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0");
|
|
||||||
const newReq = new Request(url.toString(), {
|
|
||||||
method: request.method,
|
|
||||||
headers,
|
|
||||||
body: request.body
|
|
||||||
});
|
|
||||||
const response = await fetch(newReq);
|
|
||||||
return corsResponse(response);
|
|
||||||
}
|
|
||||||
__name(handleGenericProxy, "handleGenericProxy");
|
|
||||||
async function handleImageProxy(request, env) {
|
|
||||||
const url = new URL(request.url);
|
|
||||||
const path = url.pathname.slice(2);
|
|
||||||
if (url.pathname.startsWith("/~")) {
|
|
||||||
if (env.VITE_PXIMG_BASEURL_S) {
|
|
||||||
url.href = env.VITE_PXIMG_BASEURL_S + path;
|
|
||||||
} else {
|
|
||||||
url.hostname = "s.pximg.net";
|
|
||||||
url.pathname = "/" + path;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (env.VITE_PXIMG_BASEURL_I) {
|
|
||||||
url.href = env.VITE_PXIMG_BASEURL_I + path;
|
|
||||||
} else {
|
|
||||||
url.hostname = "i.pximg.net";
|
|
||||||
url.pathname = "/" + path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const headers = new Headers();
|
|
||||||
for (const h of ["accept", "accept-encoding", "accept-language", "cache-control", "user-agent"]) {
|
|
||||||
if (request.headers.get(h)) {
|
|
||||||
headers.set(h, request.headers.get(h));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
headers.set("referer", "https://www.pixiv.net/");
|
|
||||||
headers.set("user-agent", env.USER_AGENT || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0");
|
|
||||||
const newReq = new Request(url.toString(), {
|
|
||||||
headers
|
|
||||||
});
|
|
||||||
const response = await fetch(newReq);
|
|
||||||
return corsResponse(response);
|
|
||||||
}
|
|
||||||
__name(handleImageProxy, "handleImageProxy");
|
|
||||||
async function handleUserAPI(request, env, url) {
|
|
||||||
try {
|
|
||||||
const userId = url.searchParams.get("id");
|
|
||||||
if (!userId) {
|
|
||||||
return corsResponse(new Response(JSON.stringify({ error: "User ID is required" }), {
|
|
||||||
status: 400,
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
const pixivUrl = new URL(`https://www.pixiv.net/ajax/user/${userId}`);
|
|
||||||
const headers = new Headers();
|
|
||||||
headers.set("referer", "https://www.pixiv.net/");
|
|
||||||
headers.set("user-agent", env.USER_AGENT || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0");
|
|
||||||
const response = await fetch(pixivUrl.toString(), { headers });
|
|
||||||
if (!response.ok) {
|
|
||||||
return corsResponse(new Response(JSON.stringify({ error: `Pixiv API returned ${response.status}` }), {
|
|
||||||
status: response.status,
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
const data = await response.json();
|
|
||||||
return corsResponse(new Response(JSON.stringify(data), {
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error in user API:", error);
|
|
||||||
return corsResponse(new Response(JSON.stringify({
|
|
||||||
error: "Internal server error",
|
|
||||||
message: error instanceof Error ? error.message : "Unknown error"
|
|
||||||
}), {
|
|
||||||
status: 500,
|
|
||||||
headers: { "Content-Type": "application/json" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__name(handleUserAPI, "handleUserAPI");
|
|
||||||
async function handleStaticAssets(request, env, path) {
|
|
||||||
try {
|
|
||||||
const url = new URL(request.url);
|
|
||||||
const pathname = url.pathname;
|
|
||||||
let contentType = "text/plain";
|
|
||||||
if (pathname.endsWith(".js")) {
|
|
||||||
contentType = "application/javascript";
|
|
||||||
} else if (pathname.endsWith(".css")) {
|
|
||||||
contentType = "text/css";
|
|
||||||
} else if (pathname.endsWith(".ico")) {
|
|
||||||
contentType = "image/x-icon";
|
|
||||||
} else if (pathname.endsWith(".svg")) {
|
|
||||||
contentType = "image/svg+xml";
|
|
||||||
} else if (pathname.endsWith(".png")) {
|
|
||||||
contentType = "image/png";
|
|
||||||
} else if (pathname.endsWith(".jpg") || pathname.endsWith(".jpeg")) {
|
|
||||||
contentType = "image/jpeg";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new Response("Static asset not found", {
|
|
||||||
status: 404,
|
|
||||||
headers: { "Content-Type": "text/plain" }
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
return new Response("Static asset not found", {
|
|
||||||
status: 404,
|
|
||||||
headers: { "Content-Type": "text/plain" }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return new Response("Static asset not found", {
|
|
||||||
status: 404,
|
|
||||||
headers: { "Content-Type": "text/plain" }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__name(handleStaticAssets, "handleStaticAssets");
|
|
||||||
async function handleFrontendPage(request, env) {
|
|
||||||
const html = `<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<link rel="icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>PixivNow</title>
|
|
||||||
|
|
||||||
<!-- Umami Analytics -->
|
|
||||||
<script defer src="https://cloud.umami.is/script.js" data-website-id="842d980c-5e11-4834-a2a8-5daaa285ce66"><\/script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
||||||
sans-serif;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
text-align: center;
|
|
||||||
color: white;
|
|
||||||
max-width: 600px;
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
font-size: 1.2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 50px;
|
|
||||||
padding: 1rem 2rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
color: white;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 400px;
|
|
||||||
margin: 0 auto 2rem;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box::placeholder {
|
|
||||||
color: rgba(255, 255, 255, 0.7);
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-box:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: rgba(255, 255, 255, 0.6);
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.features {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
||||||
gap: 1rem;
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature {
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 15px;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature h3 {
|
|
||||||
margin: 0 0 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature p {
|
|
||||||
margin: 0;
|
|
||||||
opacity: 0.8;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
margin-top: 2rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background: rgba(0, 255, 0, 0.1);
|
|
||||||
border: 1px solid rgba(0, 255, 0, 0.3);
|
|
||||||
border-radius: 10px;
|
|
||||||
color: #90EE90;
|
|
||||||
}
|
|
||||||
|
|
||||||
.api-info {
|
|
||||||
margin-top: 2rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
border-radius: 10px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.api-info a {
|
|
||||||
color: #FFD700;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.api-info a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="logo">PixivNow</div>
|
|
||||||
<div class="subtitle">\u63A2\u7D22\u7CBE\u5F69\u7684 Pixiv \u4F5C\u54C1\u4E16\u754C</div>
|
|
||||||
|
|
||||||
<input type="text" class="search-box" placeholder="\u8F93\u5165\u5173\u952E\u8BCD\u6216\u753B\u5E08\u540D\u79F0\u641C\u7D22\u4F5C\u54C1..." />
|
|
||||||
|
|
||||||
<div class="features">
|
|
||||||
<div class="feature">
|
|
||||||
<h3>\u{1F3A8} \u968F\u673A\u4F5C\u54C1</h3>
|
|
||||||
<p>\u53D1\u73B0\u610F\u60F3\u4E0D\u5230\u7684\u7CBE\u5F69\u4F5C\u54C1</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h3>\u{1F50D} \u667A\u80FD\u641C\u7D22</h3>
|
|
||||||
<p>\u5FEB\u901F\u627E\u5230\u4F60\u559C\u6B22\u7684\u5185\u5BB9</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h3>\u{1F4F1} \u54CD\u5E94\u5F0F\u8BBE\u8BA1</h3>
|
|
||||||
<p>\u5B8C\u7F8E\u9002\u914D\u5404\u79CD\u8BBE\u5907</p>
|
|
||||||
</div>
|
|
||||||
<div class="feature">
|
|
||||||
<h3>\u26A1 \u9AD8\u901F\u8BBF\u95EE</h3>
|
|
||||||
<p>\u57FA\u4E8E Cloudflare \u5168\u7403\u52A0\u901F</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="status">
|
|
||||||
\u2705 \u670D\u52A1\u6B63\u5E38\u8FD0\u884C\u4E2D
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="api-info">
|
|
||||||
<p>API \u63A5\u53E3\u53EF\u7528\uFF1A</p>
|
|
||||||
<p><a href="/api/illust/random">/api/illust/random</a> - \u968F\u673A\u4F5C\u54C1</p>
|
|
||||||
<p><a href="/api/user">/api/user</a> - \u7528\u6237\u4FE1\u606F</p>
|
|
||||||
<p>\u56FE\u7247\u4EE3\u7406\uFF1A<code>/i/</code> \u548C <code>/s/</code></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// \u7B80\u5355\u7684\u641C\u7D22\u529F\u80FD\u6F14\u793A
|
|
||||||
document.querySelector('.search-box').addEventListener('keypress', function(e) {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
const query = this.value.trim();
|
|
||||||
if (query) {
|
|
||||||
alert('\u641C\u7D22\u529F\u80FD\u6B63\u5728\u5F00\u53D1\u4E2D\uFF0C\u656C\u8BF7\u671F\u5F85\uFF01\\n\u641C\u7D22\u5173\u952E\u8BCD\uFF1A' + query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// \u6DFB\u52A0\u4E00\u4E9B\u4EA4\u4E92\u6548\u679C
|
|
||||||
document.querySelectorAll('.feature').forEach(feature => {
|
|
||||||
feature.addEventListener('mouseenter', function() {
|
|
||||||
this.style.transform = 'translateY(-5px)';
|
|
||||||
this.style.boxShadow = '0 10px 20px rgba(0,0,0,0.2)';
|
|
||||||
});
|
|
||||||
|
|
||||||
feature.addEventListener('mouseleave', function() {
|
|
||||||
this.style.transform = 'translateY(0)';
|
|
||||||
this.style.boxShadow = 'none';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
<\/script>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
return corsResponse(new Response(html, {
|
|
||||||
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
__name(handleFrontendPage, "handleFrontendPage");
|
|
||||||
|
|
||||||
// node_modules/.pnpm/wrangler@4.42.1/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts
|
|
||||||
var drainBody = /* @__PURE__ */ __name(async (request, env, _ctx, middlewareCtx) => {
|
|
||||||
try {
|
|
||||||
return await middlewareCtx.next(request, env);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (request.body !== null && !request.bodyUsed) {
|
|
||||||
const reader = request.body.getReader();
|
|
||||||
while (!(await reader.read()).done) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to drain the unused request body.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, "drainBody");
|
|
||||||
var middleware_ensure_req_body_drained_default = drainBody;
|
|
||||||
|
|
||||||
// node_modules/.pnpm/wrangler@4.42.1/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts
|
|
||||||
function reduceError(e) {
|
|
||||||
return {
|
|
||||||
name: e?.name,
|
|
||||||
message: e?.message ?? String(e),
|
|
||||||
stack: e?.stack,
|
|
||||||
cause: e?.cause === void 0 ? void 0 : reduceError(e.cause)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
__name(reduceError, "reduceError");
|
|
||||||
var jsonError = /* @__PURE__ */ __name(async (request, env, _ctx, middlewareCtx) => {
|
|
||||||
try {
|
|
||||||
return await middlewareCtx.next(request, env);
|
|
||||||
} catch (e) {
|
|
||||||
const error = reduceError(e);
|
|
||||||
return Response.json(error, {
|
|
||||||
status: 500,
|
|
||||||
headers: { "MF-Experimental-Error-Stack": "true" }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, "jsonError");
|
|
||||||
var middleware_miniflare3_json_error_default = jsonError;
|
|
||||||
|
|
||||||
// .wrangler/tmp/bundle-xddOtL/middleware-insertion-facade.js
|
|
||||||
var __INTERNAL_WRANGLER_MIDDLEWARE__ = [
|
|
||||||
middleware_ensure_req_body_drained_default,
|
|
||||||
middleware_miniflare3_json_error_default
|
|
||||||
];
|
|
||||||
var middleware_insertion_facade_default = path_default;
|
|
||||||
|
|
||||||
// node_modules/.pnpm/wrangler@4.42.1/node_modules/wrangler/templates/middleware/common.ts
|
|
||||||
var __facade_middleware__ = [];
|
|
||||||
function __facade_register__(...args) {
|
|
||||||
__facade_middleware__.push(...args.flat());
|
|
||||||
}
|
|
||||||
__name(__facade_register__, "__facade_register__");
|
|
||||||
function __facade_invokeChain__(request, env, ctx, dispatch, middlewareChain) {
|
|
||||||
const [head, ...tail] = middlewareChain;
|
|
||||||
const middlewareCtx = {
|
|
||||||
dispatch,
|
|
||||||
next(newRequest, newEnv) {
|
|
||||||
return __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return head(request, env, ctx, middlewareCtx);
|
|
||||||
}
|
|
||||||
__name(__facade_invokeChain__, "__facade_invokeChain__");
|
|
||||||
function __facade_invoke__(request, env, ctx, dispatch, finalMiddleware) {
|
|
||||||
return __facade_invokeChain__(request, env, ctx, dispatch, [
|
|
||||||
...__facade_middleware__,
|
|
||||||
finalMiddleware
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
__name(__facade_invoke__, "__facade_invoke__");
|
|
||||||
|
|
||||||
// .wrangler/tmp/bundle-xddOtL/middleware-loader.entry.ts
|
|
||||||
var __Facade_ScheduledController__ = class ___Facade_ScheduledController__ {
|
|
||||||
constructor(scheduledTime, cron, noRetry) {
|
|
||||||
this.scheduledTime = scheduledTime;
|
|
||||||
this.cron = cron;
|
|
||||||
this.#noRetry = noRetry;
|
|
||||||
}
|
|
||||||
static {
|
|
||||||
__name(this, "__Facade_ScheduledController__");
|
|
||||||
}
|
|
||||||
#noRetry;
|
|
||||||
noRetry() {
|
|
||||||
if (!(this instanceof ___Facade_ScheduledController__)) {
|
|
||||||
throw new TypeError("Illegal invocation");
|
|
||||||
}
|
|
||||||
this.#noRetry();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
function wrapExportedHandler(worker) {
|
|
||||||
if (__INTERNAL_WRANGLER_MIDDLEWARE__ === void 0 || __INTERNAL_WRANGLER_MIDDLEWARE__.length === 0) {
|
|
||||||
return worker;
|
|
||||||
}
|
|
||||||
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
|
||||||
__facade_register__(middleware);
|
|
||||||
}
|
|
||||||
const fetchDispatcher = /* @__PURE__ */ __name(function(request, env, ctx) {
|
|
||||||
if (worker.fetch === void 0) {
|
|
||||||
throw new Error("Handler does not export a fetch() function.");
|
|
||||||
}
|
|
||||||
return worker.fetch(request, env, ctx);
|
|
||||||
}, "fetchDispatcher");
|
|
||||||
return {
|
|
||||||
...worker,
|
|
||||||
fetch(request, env, ctx) {
|
|
||||||
const dispatcher = /* @__PURE__ */ __name(function(type, init) {
|
|
||||||
if (type === "scheduled" && worker.scheduled !== void 0) {
|
|
||||||
const controller = new __Facade_ScheduledController__(
|
|
||||||
Date.now(),
|
|
||||||
init.cron ?? "",
|
|
||||||
() => {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return worker.scheduled(controller, env, ctx);
|
|
||||||
}
|
|
||||||
}, "dispatcher");
|
|
||||||
return __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
__name(wrapExportedHandler, "wrapExportedHandler");
|
|
||||||
function wrapWorkerEntrypoint(klass) {
|
|
||||||
if (__INTERNAL_WRANGLER_MIDDLEWARE__ === void 0 || __INTERNAL_WRANGLER_MIDDLEWARE__.length === 0) {
|
|
||||||
return klass;
|
|
||||||
}
|
|
||||||
for (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {
|
|
||||||
__facade_register__(middleware);
|
|
||||||
}
|
|
||||||
return class extends klass {
|
|
||||||
#fetchDispatcher = /* @__PURE__ */ __name((request, env, ctx) => {
|
|
||||||
this.env = env;
|
|
||||||
this.ctx = ctx;
|
|
||||||
if (super.fetch === void 0) {
|
|
||||||
throw new Error("Entrypoint class does not define a fetch() function.");
|
|
||||||
}
|
|
||||||
return super.fetch(request);
|
|
||||||
}, "#fetchDispatcher");
|
|
||||||
#dispatcher = /* @__PURE__ */ __name((type, init) => {
|
|
||||||
if (type === "scheduled" && super.scheduled !== void 0) {
|
|
||||||
const controller = new __Facade_ScheduledController__(
|
|
||||||
Date.now(),
|
|
||||||
init.cron ?? "",
|
|
||||||
() => {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return super.scheduled(controller);
|
|
||||||
}
|
|
||||||
}, "#dispatcher");
|
|
||||||
fetch(request) {
|
|
||||||
return __facade_invoke__(
|
|
||||||
request,
|
|
||||||
this.env,
|
|
||||||
this.ctx,
|
|
||||||
this.#dispatcher,
|
|
||||||
this.#fetchDispatcher
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
__name(wrapWorkerEntrypoint, "wrapWorkerEntrypoint");
|
|
||||||
var WRAPPED_ENTRY;
|
|
||||||
if (typeof middleware_insertion_facade_default === "object") {
|
|
||||||
WRAPPED_ENTRY = wrapExportedHandler(middleware_insertion_facade_default);
|
|
||||||
} else if (typeof middleware_insertion_facade_default === "function") {
|
|
||||||
WRAPPED_ENTRY = wrapWorkerEntrypoint(middleware_insertion_facade_default);
|
|
||||||
}
|
|
||||||
var middleware_loader_entry_default = WRAPPED_ENTRY;
|
|
||||||
export {
|
|
||||||
__INTERNAL_WRANGLER_MIDDLEWARE__,
|
|
||||||
middleware_loader_entry_default as default
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=%5B%5Bpath%5D%5D.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -20,8 +20,10 @@ function corsResponse(response: Response) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { getAssetFromKV } from '@cloudflare/kv-asset-handler'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fetch: async (request: Request, env: any, ctx: any) => {
|
async fetch(request: Request, env: any, ctx: any): Promise<Response> {
|
||||||
console.log('Worker fetch called:', request.method, request.url)
|
console.log('Worker fetch called:', request.method, request.url)
|
||||||
|
|
||||||
const url = new URL(request.url)
|
const url = new URL(request.url)
|
||||||
@@ -55,15 +57,58 @@ export default {
|
|||||||
if (path === '/api/user') {
|
if (path === '/api/user') {
|
||||||
return await handleUserAPI(request, env, url)
|
return await handleUserAPI(request, env, url)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 静态资源处理
|
// 静态资源和前端页面处理
|
||||||
if (path.startsWith('/assets/') || path === '/favicon.ico' || path === '/robots.txt' || path.startsWith('/images/')) {
|
// 使用新的 Assets API
|
||||||
return await handleStaticAssets(request, env, path)
|
if (env.ASSETS) {
|
||||||
|
try {
|
||||||
|
return await env.ASSETS.fetch(request)
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Asset not found, falling back to index.html')
|
||||||
|
// 如果静态资源不存在,返回 index.html(SPA 路由处理)
|
||||||
|
try {
|
||||||
|
const indexRequest = new Request(new URL('/index.html', request.url), request)
|
||||||
|
return await env.ASSETS.fetch(indexRequest)
|
||||||
|
} catch (indexError) {
|
||||||
|
console.log('Index.html not found, using fallback')
|
||||||
|
// 如果 index.html 也不存在,返回内置的前端页面
|
||||||
|
return await handleFrontendPage(request, env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有 ASSETS,使用 getAssetFromKV
|
||||||
|
try {
|
||||||
|
return await getAssetFromKV(
|
||||||
|
{
|
||||||
|
request,
|
||||||
|
waitUntil: ctx.waitUntil.bind(ctx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ASSET_NAMESPACE: env.__STATIC_CONTENT,
|
||||||
|
ASSET_MANIFEST: env.__STATIC_CONTENT_MANIFEST,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
// 如果静态资源不存在,返回 index.html(SPA 路由处理)
|
||||||
|
try {
|
||||||
|
const indexRequest = new Request(new URL('/index.html', request.url), request)
|
||||||
|
return await getAssetFromKV(
|
||||||
|
{
|
||||||
|
request: indexRequest,
|
||||||
|
waitUntil: ctx.waitUntil.bind(ctx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ASSET_NAMESPACE: env.__STATIC_CONTENT,
|
||||||
|
ASSET_MANIFEST: env.__STATIC_CONTENT_MANIFEST,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (indexError) {
|
||||||
|
// 如果 index.html 也不存在,返回内置的前端页面
|
||||||
|
return await handleFrontendPage(request, env)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根路径和其他路径都返回前端页面(SPA 路由)
|
|
||||||
return await handleFrontendPage(request, env)
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Worker error:', error)
|
console.error('Worker error:', error)
|
||||||
return corsResponse(new Response(JSON.stringify({
|
return corsResponse(new Response(JSON.stringify({
|
||||||
@@ -338,50 +383,14 @@ async function handleUserAPI(request: Request, env: any, url: URL) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 静态资源处理器
|
// 静态资源处理器(已废弃,现在使用 getAssetFromKV)
|
||||||
async function handleStaticAssets(request: Request, env: any, path: string) {
|
// async function handleStaticAssets(request: Request, env: any, path: string) {
|
||||||
try {
|
// // 这个函数已经被 getAssetFromKV 替代
|
||||||
const url = new URL(request.url)
|
// return new Response('Static asset not found', {
|
||||||
const pathname = url.pathname
|
// status: 404,
|
||||||
|
// headers: { 'Content-Type': 'text/plain' }
|
||||||
// 根据文件扩展名设置 Content-Type
|
// })
|
||||||
let contentType = 'text/plain'
|
// }
|
||||||
if (pathname.endsWith('.js')) {
|
|
||||||
contentType = 'application/javascript'
|
|
||||||
} else if (pathname.endsWith('.css')) {
|
|
||||||
contentType = 'text/css'
|
|
||||||
} else if (pathname.endsWith('.ico')) {
|
|
||||||
contentType = 'image/x-icon'
|
|
||||||
} else if (pathname.endsWith('.svg')) {
|
|
||||||
contentType = 'image/svg+xml'
|
|
||||||
} else if (pathname.endsWith('.png')) {
|
|
||||||
contentType = 'image/png'
|
|
||||||
} else if (pathname.endsWith('.jpg') || pathname.endsWith('.jpeg')) {
|
|
||||||
contentType = 'image/jpeg'
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试读取文件
|
|
||||||
try {
|
|
||||||
// 这里需要使用 Cloudflare Workers 的文件系统 API
|
|
||||||
// 由于 Workers 环境限制,我们需要将文件内容嵌入到代码中
|
|
||||||
// 或者使用 KV 存储
|
|
||||||
return new Response('Static asset not found', {
|
|
||||||
status: 404,
|
|
||||||
headers: { 'Content-Type': 'text/plain' }
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
return new Response('Static asset not found', {
|
|
||||||
status: 404,
|
|
||||||
headers: { 'Content-Type': 'text/plain' }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return new Response('Static asset not found', {
|
|
||||||
status: 404,
|
|
||||||
headers: { 'Content-Type': 'text/plain' }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 前端页面处理器
|
// 前端页面处理器
|
||||||
async function handleFrontendPage(request: Request, env: any) {
|
async function handleFrontendPage(request: Request, env: any) {
|
||||||
|
|||||||
189
temp_response.html
Normal file
189
temp_response.html
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>PixivNow</title>
|
||||||
|
|
||||||
|
<!-- Umami Analytics -->
|
||||||
|
<script defer src="https://cloud.umami.is/script.js" data-website-id="842d980c-5e11-4834-a2a8-5daaa285ce66"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
max-width: 600px;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 50px;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: white;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto 2rem;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: rgba(255, 255, 255, 0.6);
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 15px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature h3 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature p {
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: rgba(0, 255, 0, 0.1);
|
||||||
|
border: 1px solid rgba(0, 255, 0, 0.3);
|
||||||
|
border-radius: 10px;
|
||||||
|
color: #90EE90;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-info {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-info a {
|
||||||
|
color: #FFD700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-info a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="logo">PixivNow</div>
|
||||||
|
<div class="subtitle">探索精彩的 Pixiv 作品世界</div>
|
||||||
|
|
||||||
|
<input type="text" class="search-box" placeholder="输入关键词或画师名称搜索作品..." />
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
<div class="feature">
|
||||||
|
<h3>🎨 随机作品</h3>
|
||||||
|
<p>发现意想不到的精彩作品</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>🔍 智能搜索</h3>
|
||||||
|
<p>快速找到你喜欢的内容</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>📱 响应式设计</h3>
|
||||||
|
<p>完美适配各种设备</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>⚡ 高速访问</h3>
|
||||||
|
<p>基于 Cloudflare 全球加速</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="status">
|
||||||
|
✅ 服务正常运行中
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="api-info">
|
||||||
|
<p>API 接口可用:</p>
|
||||||
|
<p><a href="/api/illust/random">/api/illust/random</a> - 随机作品</p>
|
||||||
|
<p><a href="/api/user">/api/user</a> - 用户信息</p>
|
||||||
|
<p>图片代理:<code>/i/</code> 和 <code>/s/</code></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 简单的搜索功能演示
|
||||||
|
document.querySelector('.search-box').addEventListener('keypress', function(e) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
const query = this.value.trim();
|
||||||
|
if (query) {
|
||||||
|
alert('搜索功能正在开发中,敬请期待!\n搜索关键词:' + query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 添加一些交互效果
|
||||||
|
document.querySelectorAll('.feature').forEach(feature => {
|
||||||
|
feature.addEventListener('mouseenter', function() {
|
||||||
|
this.style.transform = 'translateY(-5px)';
|
||||||
|
this.style.boxShadow = '0 10px 20px rgba(0,0,0,0.2)';
|
||||||
|
});
|
||||||
|
|
||||||
|
feature.addEventListener('mouseleave', function() {
|
||||||
|
this.style.transform = 'translateY(0)';
|
||||||
|
this.style.boxShadow = 'none';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
46
temp_response2.html
Normal file
46
temp_response2.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>PixivNow</title>
|
||||||
|
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<!-- <script
|
||||||
|
async
|
||||||
|
src="https://www.googletagmanager.com/gtag/js?id=%VITE_GOOGLE_ANALYTICS_ID%"
|
||||||
|
></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || []
|
||||||
|
function gtag() {
|
||||||
|
dataLayer.push(arguments)
|
||||||
|
}
|
||||||
|
gtag('js', new Date())
|
||||||
|
gtag('config', '%VITE_GOOGLE_ANALYTICS_ID%')
|
||||||
|
</script> -->
|
||||||
|
<!-- Umami Analytics -->
|
||||||
|
<script defer src="https://cloud.umami.is/script.js" data-website-id="842d980c-5e11-4834-a2a8-5daaa285ce66"></script>
|
||||||
|
<!-- Google Search Console -->
|
||||||
|
<meta
|
||||||
|
name="google-site-verification"
|
||||||
|
content="%VITE_GOOGLE_SEARCH_CONSOLE_VERIFICATION%"
|
||||||
|
/>
|
||||||
|
<!-- Google AdSense -->
|
||||||
|
<script
|
||||||
|
async
|
||||||
|
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=%VITE_ADSENSE_PUB_ID%"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
<!-- jQuery -->
|
||||||
|
<!-- <script src="https://unpkg.com/jquery@3.7.1/dist/jquery.js"></script> -->
|
||||||
|
<script type="module" crossorigin src="/assets/index-DrUt9IKo.js"></script>
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-Dleou5i9.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
This site requires JavaScript enabled. Please check your browser settings.
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
|
||||||
|
</body>
|
||||||
Reference in New Issue
Block a user