How can I achieve redirect/rewrites in Netlify?

Context:

I’m migrating monorepo’s frontend apps from Cloudflare from Netlify.
I deployed workers for redirects in Cloudflare like this:

# backend/redirect contains src/index.js, package.json, wrangler.toml

# src/index.js
export default {
	async fetch(request) {
		const url = new URL(request.url);

		let split = url.hostname.split(".");

		if (split[0] === "www") {
			split = split.slice(1);
		}

		let subdomain;

		if (split.length >= 3) {
			subdomain = split[0];
		}

		switch (subdomain) {
			case "brands":
				url.hostname = "brand-661.pages.dev";
				break;

			case "docs":
				url.hostname = "docs-cmx.pages.dev";
				break;

			default:
				const search = new URLSearchParams(request.url.search);

				if (subdomain) {
					search.set("brand", subdomain);
				}

				url.hostname = "consumer-1ja.pages.dev";
				url.search = "?" + search.toString();
		}

		return await fetch(new Request(url, request), {
			cf: {
				cacheTtl: 60,
			},
		});
	},
};

I added CNAME DNS record (example.com / redirect.example.workers.dev, *.example.com / redirect.example.workers.dev) redirect the workers name.

Question:

How can I achieve the above in Netlify?

What I tried:

  • I added an app under backend (backend/redirect-netlify) and placed only netlify.toml and package.json.
# netlify.toml

[[redirects]]
from = "https://brands.example.com/*"
to = "https://brand-661.pages.dev/:splat"
status = 200


[[redirects]]
from = "https://docs.example.com/*"
to = "https://docs-cmx.pages.dev/:splat"
status = 200

# Default rule for any other subdomain
[[redirects]]
from = "https://:subdomain.example.com/*"
to = "https://consumer-1ja.pages.dev/:splat"
status = 200

Netlify says the last redirect ruls is an invalid syntax.

  • I tried with Netlify functions. Placed functions/index.js, public/_redirects.
# functions/index.js
exports.handler = async function (event, context) {
	const url = new URL(event.rawUrl);

	let split = url.hostname.split(".");

	if (split[0] === "www") {
		split = split.slice(1);
	}

	let subdomain;

	if (split.length >= 3) {
		subdomain = split[0];
	}

	switch (subdomain) {
		case "brands":
			url.hostname = "brand.netlify.app";
			break;

		case "docs":
			url.hostname = "docs.netlify.app";
			break;

		default:
			const search = new URLSearchParams(url.search);
			if (subdomain) {
				search.set("brand", subdomain);
			}

			url.hostname = "consumer.netlify.app";
			url.search = "?" + search.toString();
	}

	return await fetch(new Request(url), {
		cf: {
			cacheTtl: 60,
		},
	});

	// const response = await fetch(url);
	// const body = response.body();

	// return {
	// 	statusCode: 200,
	// 	body: body
	// };
};

# public/_redirects
/* /.netlify/functions/index 200

This doesn’t work neither.

Side Question:
Although I added domain example.com to Neltify and DNS record (*.example.com / redirect.netlify.app), https://docs.example.com shows certification error.

Hope your great support.

Thanks.

This is indeed not supported. If you wish to match the hostname dynamically, you’d have to use Edge Functions: Edge Functions overview | Netlify Docs

Wildcard certificates can only be issued if your DNS is managed by Netlify. Since you’ve not mentioned the domain, that’s not something we can check.

Hi @hrishikesh , thanks for your support.

  • I’ve added a project to the monorepo, which is called rewrite. Let me share the codebase.
    backend/rewrite
    /netlify/edge-functions/rewrite.js
    /netlify.toml
    /package.json
export default (request) => {
	const url = new URL(request.rawUrl);
	const search = new URLSearchParams(url.search);

	let split = url.hostname.split(".");

	if (split[0] === "www") {
		split = split.slice(1);
	}

	let subdomain;

	if (split.length >= 4) {
		subdomain = split[0];
	}

	switch (subdomain) {
		case "brands":
			url.hostname = "joltz-brand.netlify.app";
			break;

		case "embed":
			url.hostname = "joltz-embed.netlify.app";
			break;

		case "philanthrobit-referrals":
			url.hostname = "joltz-referral.netlify.app";
			break;

		case "docs":
			url.hostname = "joltz-docs.netlify.app";
			break;

		case "spinner":
			if (search.has("brand", "mrsatoshi")) {
				return Response.redirect("https://staging.joltz.app/spinner/e41349b1-8c15-41ec-ad7c-7c818e4d64ec", 301);
			}

		default:
			if (subdomain) {
				search.set("brand", subdomain);
			}

			url.hostname = "joltz-consumer.netlify.app";
			url.search = "?" + search.toString();
	}

	return url;
};

export const config = {};
[build]
command = "echo No build for this site, we are living on the edge"
{
	"name": "@joltzrewards/rewrite-backend",
	"packageManager": "yarn@3.6.0"
}

And I deployed the project backend/rewrite, the build logs said it detected edge-function

10:45:46 PM: Edge Functions bundling                                       
10:45:46 PM: ────────────────────────────────────────────────────────────────
10:45:46 PM: ​
10:45:46 PM: Packaging Edge Functions from backend/rewrite/netlify/edge-functions directory:
10:45:46 PM:  - rewrite
10:45:48 PM: ​
10:45:48 PM: (Edge Functions bundling completed in 1.8s)

Build setting is

**Runtime** Not set
**Base directory** /
**Package directory** backend/rewrite
**Build command** echo No build for this site, we are living on the edge
**Publish directory** Not set
**Functions directory** netlify/functions
**Build status** Active

But when I hit staging.joltz.app (or joltz-rewrite.netlify.app), it says Page Not Found, meaning that it’s not rewriting.

And the deploy summary says “no edge function deployed”.

What’s wrong with my approach?

  • The domain is staging.joltz.app.

Looking forward to your support.

You’re not setting the config here.

Based on this, you’re not setting the config here either.

Edge Functions would only be deployed if you setat least 1 path for them to run. You can do it within the function itself or using netlify.toml.

I didn’t set edge function path, because I already placed it in the default path (backend/rewrite/netlify/edge-functions). Can you explain me more details what I should do? What if I remove that config object?

The site is joltz-rewrite.netlify.app and I want this to be happen: when a user hits https://joltz-rewrite.netlify.app, it goes though the edge function directly.

Edge Functions don’t have any default path. You always need to specify a path to invoke the Edge Function on.

export const config = {
  path: "/*"
}
1 Like

Awesome it works! I logged request.url in the edge function, it shows me https://658c2da9ee31f7000820fe31--joltz-rewrite.netlify.app/ although I expected https://staging.joltz.app because I’m hitting https://staging.joltz.app in the browser. Need updates in the configuration?

I tried visiting your site and I can see the req.url being logged correctly.

Sorry but no, It’s logging https://658c2da9ee31f7000820fe31--joltz-rewrite.netlify.app/ though I expected staging.joltz.app.

Hi, @tedzchow. The site in question was deleted. If there are further questions, let us know what site the function is deployed to.