@aziontech/opennextjs-azion
Version:
Azion builder for next apps
98 lines (97 loc) • 4.07 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* This code was originally copied and modified from the @opennextjs/cloudflare repository.
* Significant changes have been made to adapt it for use with Azion.
*/
//@ts-expect-error: Will be resolved by wrangler build
import { runWithAzionRequestContext } from "./azion/init.js";
// This is a workaround for the Azion Storage API
const bucketName = globalThis.AZION_BUCKET_NAME ?? "";
const InstanceStorage = new globalThis.Azion.Storage(bucketName);
export default {
// TODO: change to event to request when available on Azion Bundler
async fetch(event, env, ctx) {
// TODO: load the env and ctx from the global scope
// remove this when bindings are available
ctx = {
waitUntil: event.waitUntil.bind(event),
passThroughOnException: event.passThroughOnException,
request: event.request,
props: {},
};
env = {
...env,
// bind the env to the worker
AZION: {
BUCKET_NAME: globalThis.AZION_BUCKET_NAME ?? "",
BUCKET_PREFIX: globalThis.AZION_BUCKET_PREFIX ?? "",
CACHE_API_STORAGE_NAME: globalThis.AZION_CACHE_API_STORAGE_NAME ?? "nextjs_cache",
Storage: InstanceStorage,
},
ASSETS: {
fetch: getStorageAsset,
},
WORKER_SELF_REFERENCE: {
fetch: async (url, options) => {
const request = new Request(url, options);
ctx = {
...ctx,
request,
};
return requestHandler(request, env, ctx);
},
},
};
return runWithAzionRequestContext(event.request, env, ctx, async () => {
return requestHandler(event.request, env, ctx);
});
},
};
const requestHandler = async (request, env, ctx) => {
const url = new URL(request.url);
// This is a workaround for rewrite next.config
// Issue: https://github.com/opennextjs/opennextjs-aws/issues/848
request.headers.set("x-original-url", url.pathname);
// Serve images in development.
// Note: "/data-cache/image/..." requests do not reach production workers.
// TODO: make support for this
if (url.pathname.startsWith("/data-cache/image/")) {
const m = url.pathname.match(/\/data-cache\/image\/.+?\/(?<url>.+)$/);
if (m === null) {
return new Response("Not Found!", { status: 404 });
}
const imageUrl = m.groups.url;
return imageUrl.match(/^https?:\/\//) ? fetch(imageUrl) : env.ASSETS?.fetch(new URL(`/${imageUrl}`, url));
}
// Fallback for the Next default image loader.
if (url.pathname === "/_next/image") {
const imageUrl = url.searchParams.get("url") ?? "";
return imageUrl.startsWith("/") ? env.ASSETS?.fetch(new URL(imageUrl, request.url)) : fetch(imageUrl);
}
// static assets
if (url.pathname.startsWith("/_next/")) {
return env.ASSETS?.fetch(request);
}
const assetRegex = /\.(css|js|ttf|woff|woff2|pdf|svg|jpg|jpeg|gif|bmp|png|ico|mp4|json|xml)$/;
if (url.pathname.match(assetRegex)) {
if (url.pathname.includes("com.chrome.devtools.json")) {
return new Response("ok", { status: 200 });
}
return env.ASSETS?.fetch(request);
}
// @ts-expect-error: resolved by wrangler build
const { handler } = await import("./server-functions/default/handler.mjs");
return handler(request, env, {
waitUntil: ctx.waitUntil.bind(ctx),
});
};
const getStorageAsset = async (request) => {
try {
const requestPath = decodeURIComponent(new URL(request.url).pathname);
const assetUrl = new URL(requestPath === "/" ? "index.html" : requestPath, "file://");
return fetch(assetUrl);
}
catch (e) {
return new Response(e.message || e.toString(), { status: 404 });
}
};