Open tunnckoCore opened 1 month ago
My current workaround is to detect if it's data:
url, download it to the assets
folder and rewrite the url of the request as it's trying local file and deleting that file after that.
import { createApp, toWebHandler } from "h3";
import {
createIPX,
createIPXH3App,
createIPXH3Handler,
ipxFSStorage,
ipxHttpStorage,
} from "ipx";
import { rm as remove } from "node:fs/promises";
const ipx = createIPX({
storage: ipxFSStorage({ dir: "./assets" }),
httpStorage: ipxHttpStorage({ allowAllDomains: true, maxAge: 60 * 60 * 24 }),
});
export const app = createApp().use("/optimize", createIPXH3Handler(ipx));
const handler = toWebHandler(app);
Bun.serve({
port: 3000,
async fetch(req) {
let url = new URL(req.url);
if (url.pathname.startsWith("/optimize")) {
const [_, seg] = url.pathname.split("/optimize/");
const index = seg.indexOf("data");
const fpath = index === -1 ? seg : seg.slice(index);
let digest;
// download it locally to the assets folder, then delete
// at least until https://github.com/unjs/ipx/issues/244
if (fpath.startsWith("data:")) {
const buf = await fetch(fpath).then((res) => res.arrayBuffer());
digest = await createDigest(new Uint8Array(buf));
await Bun.write(`./assets/${digest}`, buf);
const resp = await handler(
new Request(
`${url.origin}/optimize/${seg.slice(0, index - 1)}/${digest}`,
req,
),
);
remove(`./assets/${digest}`);
return resp;
}
return handler(req);
}
return new Response("Not found", { status: 404 });
},
});
async function createDigest(
msg: string | Uint8Array,
algo: "SHA-1" | "SHA-256" | "SHA-512" = "SHA-256",
) {
const data = typeof msg === "string" ? new TextEncoder().encode(msg) : msg;
const hashBuffer = await crypto.subtle.digest(algo, data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
return hashHex;
}
Describe the feature
It would be pretty basic option, basically skipping the
url.hostname
check invalidateId
or the validation altogther https://github.com/unjs/ipx/blob/main/src/storage/http.ts#99Everything else can stay the same and actually work, because Fetch can fetch data URLs.
Additional information
example URI
And of course, there could be URL limit hit this way, but for small images it's okay (as above)
Other way would be to expose a similar thing programmatically accepting buffers.