Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ describe('has_trailing_slash', () => {
});

describe('subdomain_to_path', () => {
test('maps the main webflow subdomain to the root path', () => {
expect(subdomain_to_path('wf.finsweet.com')).toEqual([]);
});

test('prefers the most specific configured subdomain', () => {
expect(subdomain_to_path('components.changelog.finsweet.com')).toEqual([
'components',
Expand Down Expand Up @@ -59,7 +63,10 @@ describe('path_to_subdomain', () => {
});
});

test('returns undefined when the first path is not configured', () => {
expect(path_to_subdomain(['random'])).toBeUndefined();
test('falls back to the main webflow subdomain when path is not configured', () => {
expect(path_to_subdomain(['random'])).toEqual({
subdomain: 'wf',
wildcard_paths: ['random'],
});
});
});
14 changes: 13 additions & 1 deletion src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { env } from 'cloudflare:workers';

import { SUBDOMAINS_DATA } from './constants';

/**
Expand All @@ -22,6 +24,7 @@ export const has_trailing_slash = (pathname: string) => /\/+$/.test(pathname);

/**
* Tries to match a hostname to a reverse proxied subdomain.
* If the hostname is the webflow subdomain, it returns an empty array to indicate that the request should be proxied to the root of the main Webflow project.
*
* @param hostname
* @returns An array with the paths that correspond to the reverse proxied subdomain.
Expand All @@ -30,8 +33,13 @@ export const has_trailing_slash = (pathname: string) => /\/+$/.test(pathname);
* "attributes.finsweet.com" => ["attributes"]
* "attributes.combos.finsweet.com" => ["attributes", "combos"]
* "random.finsweet.com" => undefined
* "wf.finsweet.com" => []
*/
export const subdomain_to_path = (hostname: string) => {
if (hostname.startsWith(`${env.WEBFLOW_SUBDOMAIN}.`)) {
return [];
}

const match = SUBDOMAINS_DATA.find((sub_subdomains) => {
const subdomain = sub_subdomains.join('.');

Expand All @@ -43,6 +51,7 @@ export const subdomain_to_path = (hostname: string) => {

/**
* Tries to match an array of paths to a reverse proxied subdomain.
* If no subdomain is matched, it returns the main Webflow subdomain with all paths as wildcard paths.
* @param paths
*
* @returns The matched subdomain and the wildcard paths
Expand All @@ -52,7 +61,7 @@ export const subdomain_to_path = (hostname: string) => {
* ["attributes", "random"] => { subdomain: "attributes", wildcard_paths: ["random"] }
* ["attributes", "combos"] => { subdomain: "attributes.combos", wildcard_paths: [] }
* ["attributes", "combos", "random"] => { subdomain: "attributes.combos", wildcard_paths: ["random"] }
* ["random"] => undefined
* ["random"] => { subdomain: env.WEBFLOW_SUBDOMAIN, wildcard_paths: ["random"] }
*/
export const path_to_subdomain = (paths: string[]) => {
const match = SUBDOMAINS_DATA.find((sub_subdomains) =>
Expand All @@ -65,4 +74,7 @@ export const path_to_subdomain = (paths: string[]) => {

return { subdomain, wildcard_paths };
}

// If no subdomains are matched, fetch from the main Webflow project
return { subdomain: env.WEBFLOW_SUBDOMAIN, wildcard_paths: paths };
};
26 changes: 5 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { rewrite_sitemap_locs } from './sitemaps';
const app = new Hono<{ Bindings: Cloudflare.Env }>();

app.use('*', async (c) => {
const { DOMAIN, WEBFLOW_SUBDOMAIN, MAINTENANCE_HREF } = c.env;
const { DOMAIN, MAINTENANCE_HREF } = c.env;
const { origin, hostname, pathname, search, href } = new URL(c.req.url);

const is_under_maintenance = MAINTENANCE_HREF && href.startsWith(MAINTENANCE_HREF);
Expand All @@ -27,13 +27,6 @@ app.use('*', async (c) => {
return c.redirect(redirect_url, 301);
}

// Subdomain is the main Webflow project
if (hostname.startsWith(`${WEBFLOW_SUBDOMAIN}.`)) {
const redirect_url = build_url(MAIN_ORIGIN, paths, search);

return c.redirect(redirect_url, 301);
}

// Subdomain is not reverse proxied
return fetch(c.req.raw);
}
Expand All @@ -45,20 +38,11 @@ app.use('*', async (c) => {
return c.redirect(redirect_url, 301);
}

// Path matches reverse proxied subdomain
const match = path_to_subdomain(paths);
if (match) {
const { subdomain, wildcard_paths } = match;

const target_origin = `https://${subdomain}.${DOMAIN}`;
const target_url = build_url(target_origin, wildcard_paths, search);

return fetch_resource(c, target_url);
}
// Fetch the resource from the corresponding subdomain
const { subdomain, wildcard_paths } = path_to_subdomain(paths);

// If no subdomains are matched, fetch from the main Webflow project
const webflow_origin = `https://${WEBFLOW_SUBDOMAIN}.${DOMAIN}`;
const target_url = build_url(webflow_origin, paths, search);
const target_origin = `https://${subdomain}.${DOMAIN}`;
const target_url = build_url(target_origin, wildcard_paths, search);

return fetch_resource(c, target_url);
});
Expand Down