@aziontech/opennextjs-azion
Version:
Azion builder for Next.js apps
93 lines (92 loc) • 3.98 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";
// Azion Storage API
// TODO: future receive from azion env
const bucketName = globalThis?.AZION_BUCKET_NAME ?? "";
const bucketPrefix = globalThis?.AZION_BUCKET_PREFIX ?? "";
const InstanceStorage = new globalThis.Azion.Storage(bucketName);
export default {
async fetch(request, env, ctx) {
// SET env
env = {
...env,
AZION: {
BUCKET_NAME: bucketName,
BUCKET_PREFIX: bucketPrefix,
CACHE_API_STORAGE_NAME: globalThis.AZION_CACHE_API_STORAGE_NAME ?? "nextjs_cache",
Storage: InstanceStorage,
},
// TODO: future receive from azion env
ASSETS: {
fetch: getStorageAsset,
},
WORKER_SELF_REFERENCE: {
fetch: async (url, options) => {
const requestRef = new Request(url, options);
return requestHandler(requestRef, env, ctx);
},
},
};
return runWithAzionRequestContext(request, env, ctx, async () => {
return requestHandler(request, env, ctx);
});
},
};
const requestHandler = async (request, env, ctx) => {
const url = new URL(request.url);
// 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);
}
// This necessary to local server
const assetRegex = /\.(css|js|ttf|woff|woff2|otf|eot|svg|jpg|jpeg|gif|bmp|png|ico|webp|avif|heic|heif|tiff|tif|mp4|webm|avi|mov|wmv|flv|m4v|mkv|ogv|mp3|wav|ogg|m4a|aac|flac|opus|pdf|json|xml|zip|rar|tar|gz)$/;
if (url.pathname.match(assetRegex)) {
if (url.pathname.includes(".devtools.json")) {
return new Response("ok", { status: 200 });
}
return env.ASSETS?.fetch(request);
}
// - `Request`s are handled by the Next server
// @ts-expect-error: resolved by bundler build
const { handler: middlewareModule } = await import("./middleware/handler.mjs");
const cloneRequest = request.clone();
const reqOrResp = await middlewareModule(cloneRequest, env, ctx);
if (reqOrResp instanceof Response) {
return reqOrResp;
}
// @ts-expect-error: resolved by bundler build
const { handler } = await import("./server-functions/default/handler.mjs");
return handler(reqOrResp, env, ctx);
};
const getStorageAsset = async (request) => {
try {
const urlString = request instanceof Request ? request.url : request.toString();
const requestPath = decodeURIComponent(new URL(urlString).pathname);
const assetUrl = new URL(requestPath === "/" ? "index.html" : requestPath, "file://");
return fetch(assetUrl);
}
catch (e) {
return new Response(e.message || e.toString(), { status: 404 });
}
};