sbklS
Convex Community16mo ago
3 replies
sbkl

File serving in a nextjs app via http action authenticated with clerk

After looking at the docs, this is the implementation I came with for serving my files securely via http action. Any feedback appreciated.

/convex/http.ts
import { HonoWithConvex, HttpRouterWithHono } from "convex-helpers/server/hono";
import { Hono } from "hono";

import { ActionCtx } from "./_generated/server";

const app: HonoWithConvex<ActionCtx> = new Hono();

app.get("/storage", async (ctx) => {
  const identity = await ctx.env.auth.getUserIdentity();
  if (!identity?.subject) {
    return new Response("User is not signed in.", { status: 401 });
  }
  const storageId = ctx.req.query("storageId");
  const fileType = ctx.req.query("fileType");

  if (!storageId) {
    return new Response("Storage ID is required.", { status: 400 });
  }

  if (!fileType) {
    return new Response("File type is required.", { status: 400 });
  }

  switch (fileType) {
    case "document":
    case "documentThumbnail":
      await ctx.env.runQuery(internal.documents.query.verify, {
        fileType,
        storageId: storageId as Id<"_storage">,
        userExternalId: identity.subject.toString(),
      });
      break;
    default:
      return new Response("Invalid file type.", { status: 400 });
  }

  const blob = await ctx.env.storage.get(storageId as Id<"_storage">);
  if (blob === null) {
    return new Response("File not found", {
      status: 404,
    });
  }
  return new Response(blob);
});

export default new HttpRouterWithHono(app);
Was this page helpful?