pingdotgg / uploadthing

File uploads for modern web devs
https://uploadthing.com
MIT License
4.28k stars 319 forks source link

Question: How do I use uploadthing with Clerk (clashing middleware)? #165

Closed matthewspear closed 1 year ago

matthewspear commented 1 year ago

Hey 👋

I'm using Next.js with pages. Project built with create-t3-app v7.13.1.

I'm trying to use Clerk with uploadthing and inside the uploadthing middleware function I want to check the user is logged in an associate the data with the user via an id.

uploadthing.ts:

/** server/uploadthing.ts */
import type { NextApiRequest, NextApiResponse } from "next";
import { createUploadthing, type FileRouter } from "uploadthing/next-legacy";

import { getAuth } from "@clerk/nextjs/server";

const f = createUploadthing();

const auth = async (req: NextApiRequest, res: NextApiResponse) => ({
  id: getAuth(req).userId,
});

// FileRouter for your app, can contain multiple FileRoutes
export const ourFileRouter = {
  // Define as many FileRoutes as you like, each with a unique routeSlug
  textUploader: f({ text: { maxFileSize: "2MB", maxFileCount: 10 } })
    // Set permissions and file types for this FileRoute
    .middleware(async (req, res) => {
      // This code runs on your server before upload
      const user = await auth(req, res);

      // If you throw, the user will not be able to upload
      if (!user) throw new Error("Unauthorized");

      // Whatever is returned here is accessible in onUploadComplete as `metadata`
      return { userId: user.id };
    })
    .onUploadComplete(async ({ metadata, file }) => {
      // This code RUNS ON YOUR SERVER after upload
      // console.log("Upload complete for userId:", metadata.userId);

      console.log("file url", file.url);
    }),
} satisfies FileRouter;

export type OurFileRouter = typeof ourFileRouter;

middleware.ts:

import { authMiddleware } from "@clerk/nextjs";

export default authMiddleware({
  publicRoutes: ["/", "/api/uploadthing"],
});

export const config = {
  matcher: ["/((?!.*\\..*|_next).*)", "/", "/(api|trpc)(.*)"],
};

When I run this code I get errors

Frontend alert / error says "ERROR! Failed to get presigned URLs"

I've double checked my .env and API keys mentioned in another issue.

Terminal error:

[UT] UploadThing dev server is now running!
[UT] middleware failed to run
Error: You need to use "authMiddleware" (or the deprecated "withClerkMiddleware") in your Next.js middleware file. You also need to make sure that your middleware matcher is configured correctly and matches this route or page. See https://clerk.com/docs/quickstarts/get-started-with-nextjs

If I remove the Uploadthing middleware block, the upload works, but then I can't tag it / confirm the users Id.

I hope this is the right place to post / hope I can help others because this seems like a pretty common setup to run Clerk + uploadthings...

Feel free to ask for more details / info...

I've been racking my head with this one, any help would be appreciated!

GentikSolm commented 1 year ago

You middleware isn't making all of uploadThings API public, only the base route. Use something like this for your public routes publicRoutes: ['/sign-up(.*)', '/sign-in(.*)', '/api(.*)'],

Regardless, for questions there is a uploadThing discord where we can help with questions and help debug. The invite is on the ut docs.

matthewspear commented 1 year ago

I tried altering the public routes as suggested but still get the error:

Error: You need to use "authMiddleware" (or the deprecated "withClerkMiddleware") in your Next.js middleware file.

and its dependant on making the getAuth(req) which I now try, catch and the upload goes through, but I'm no closer to adding the metadata.

I do wonder how new the authMiddleware is and if its a potential issue or Next version mismatch. Edit: using "next": "^13.2.4".

I whipped up a quick project using app dir and the middleware worked fine, accessing the userId metadata but feels a tad to experimental to jump to 😱 with tRPC in the mix, and don't want to do right now.

GentikSolm commented 1 year ago

Interesting. I'll try and dig into it, but I would be surprised if this is an issue with ut itself. I am currently working on a project using trpc, app dir, clerk and ut, with all of them are functioning fine.

matthewspear commented 1 year ago

I'd really appreciate that – I've opened up a question in the Clerk discord, will report back if I find anything!

In the meanwhile I'll use the frontend onClientUploadComplete to handle my docs.

matthewspear commented 1 year ago

Just following up on this, made a demo repo to show folks over on the Clerk forum – will post here and keep this up to date as I work to solve the issue:

https://github.com/matthewspear/uploadthing-clerk-app

matthewspear commented 1 year ago

Following up on this, found a solution and posted: https://github.com/matthewspear/uploadthing-clerk-app

TLDR: