Can Pages Function Middleware change incoming request?
Hello team, nice community here! This is my first question in the discord and its very simple:
Can you rewrite (not redirect) the destination URL from inside a function middleware in pages?
The docs on middleware shows how you can intercept request destination handler and call some other tasks before it, or after it, but I would like to take that incoming request and rewrite it to a
[slug]
directory similar to the following NestJS middleware setup:
Code snippet for nextjs middleware:
import { NextRequest, NextResponse } from "next/server";
export default async function middleware(req: NextRequest) {
const url = req.nextUrl;
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
const hostname = req.headers
.get("host")!
.replace(".localhost:3000", .${process.env.NEXT_PUBLIC_ROOT_DOMAIN});
// Get the pathname of the request (e.g. /, /about, /blog/first-post)
const path = url.pathname;
// Rewrite to /[domain]/[path] dynamic route
return NextResponse.rewrite(new URL(/${hostname}${path}, req.url));
}
Snippet end
In summary, if the [slug]
is acme
then I want to rewrite acme.myapp.com
to route to nextjs app/[acme]/layout.ts
corresponding static assets from next build
, given that acme
subdomain is mapped with Cloudflare for Saas.
I was hoping to use static export of nextJS (no SSR, so it opts out of nextJS middleware altogether), along with Cloudflare Pages Functions to regain the opted out functionality, and seems like pages also has the primitives using _middleware.js
If any team member caught eye on this it would mean a lot if you can get attention of someone that is more expereinced with this regard., maybe @Walshy | Pages or the team that is working with the next-on-pages library, Looking forward!18 Replies
I'm essentially trying to allocate users of a saas app their own subdomains, and using cloudflare for saas custom hostnames to do it, and the webapp is written in nextjs
Is the redirects file and using the [slug] approach something you would recommend? Is there something else I can do (I essentially took this from the Vercel platforms starter kit repo where they are using this middleware to rewrite to a slug for each tenant of the saas
That would be absolutely a life saver I have been going at it for many hours at this point trying to find out the way to work this with nextjs!
I'm essentially trying to allocate users of a saas app their own subdomains, and using cloudflare for saas custom hostnames to do it, and the webapp is written in nextjs.
Example is allocating subdomains such as:
customer1.myapp.com,
customer2.myapp.com,
.
.
customerN.myapp.com
for each users of the saas.
On nextjs app I have /app/[slug]/index.tsx so if
customer1.myapp.com
shows up then I can take customer1
as the slug and then rest of the nextapp can use that as an id to generate the pages that are specific to this customer.
Have you seen another way to do this?
Related question that you might know answer to is that I've setup cloudflare for saas and the fallback dns entry, so now when I deploy the nextjs app how can I wire up that pages project to use that fallback entry? I only saw custom domains support in cloudflare for pages, but it doesn't support wildcard subdomains either,.. Docs show example of using a worker as the origin (originless) but I'm using pages.. Do I need to create another worker that proxys my cloudflare pages worker?
Thanks a lot for the reference, James if you have idea about this setup or if you have an alternate setup I would be so much relieved,..
And Skye my last paragraph about wiring up pages to work with the DNS is little jumbled, do you have experience with it? Should I reword that question if it was not understood fully
Here is what I did so far
I created a fallback origin and CName target using this documentation:
https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/
So at this point in my DNS I have the record:
AAAA record: proxy-fallback with value 100:: ,Proxied
CNAME record: .customers with value proxy-fallback.bidsonic.com, Proxied
Then I have created a Pages project and deployed the nextjs app. But now under the pages project, there is
an option to connect it to a custom domain, or there is this documentation of using originless mode
:
https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/
Where it shows creating a Workers Route
.. I am not following the next step from here. How do I route my CF for Saas custom hostnames
such as "customerN.myapp.com" to the deployed cloudflare pages project? Do I need to set up additional DNS records? Or use that fallback origin DNS as the custom domain? (is that possible)
Hope this was a more precise question, any ideas?
Basically I want traffic from the internet to route to the cloudflare pages deployment that I created, and normally you can do that either by using the worker.dev url that pages gives for deployment, or by adding a custom domain.. but what is the setup for using cloudflare for saas? where I have those DNS setup and the fallback originYou can't use SSL for SaaS and Pages today
But we offer tons of subdomains that you can just use instead
Can you give any pointers to this part?
what is the setup for projects using cloudflare for saas and want to deploy their site to cloudflare infrastructure
When your customer gives you their domain, use the API and send a POST to our custom domain endpoint.
Just like you do for ssl for SaaS already but instead use our endpoint
When customer gives their domain that is one part of the story, how can the other part be solved, for a setup where you have wildcard subdomains with each customer?
customer1.myapp.com,
customer2.myapp.com,
.
.
customerN.myapp.com
Something like this, I cannot use wildcard custom domains on pages either right?
I was also looking at
https://developers.cloudflare.com/workers/platform/sites/
is that with a worker Route the only way for me to accomplish what I described for now?You could potentially still make a wildcard record, just a CNAME pointing to pages.dev but not tested if that works. Other customers have just told their customers to add the pages.dev
Sites is long since deprecated in favour of Pages. You could also just have a Worker over the SaaS route like normal and have that Worker route
Another option customers take
Something like this:
https://developers.cloudflare.com/workers/platform/triggers/routes/
right?Worker sits on
*/*
, ssl for SaaS points to Worker, customers get sent to the Worker which routes to PagesIf I take that approach, say I create a worker and have ssl for saas route my traffic to that using the link above, then I proxy to pages from inside my worker, am I incurring penalty in performance? Would double the costs
performance overhead will be basically nothing, your Worker can easily run in under an ms or a few single digit depending on the logic
I mostly have the idea now, one last followup on implementing the last part you mentioned about the worker routes to the pages, how does that look in code for the worker? If i think in terms of: I need to deploy a worker that has a fetch handler and that fetch hangler then needs to call a fetch handler for pages, what would I call from the worker fetch handler to route to pages? Like some binding to the pages worker?
If it's all to a single Pages app you'd do
If its different projects per customer you'd need to do the logic to route them to the right one
Thanks, I will implement and come back with what I found after, really appreciate the help! The puzzle is almost solved I hope James has something for me after reading all this thread on if this is still possible with SSR on Nextjs. Thanks a lot Walshy
No worries. It's been on the todo list to write docs on this
We just haven't yet
If you're using SSR, Next.js middleware should work fine with rewrites. I haven't tried out the middleware code in the platforms starter, but we do have tests for doing rewrites in middleware that work fine, so I would imagine it'll be okay.
If you do encounter any issues with the Next.js middleware for a multi-tenanted app, please do let me know exactly what so I can look into it - not sure if multi-tenanted will introduce a weird edge case or not.
I am implementing this right now and I really appreciate that you are interested in finding out the edge cases too. Small followup, do you think this middleware rewrite is a good approach to having a subdomain per tenant? Or if you have seen something that is different
middleware rewrites are generally the recommended way to do multi-tenanted apps with nextjs, so i would stick with that
Awesome thanks James!