-
Notifications
You must be signed in to change notification settings - Fork 10k
Add hostname routing page #23361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add hostname routing page #23361
Changes from 2 commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
112 changes: 112 additions & 0 deletions
112
...cloudflare-for-platforms/workers-for-platforms/get-started/hostname-routing.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| --- | ||
| pcx_content_type: how-to | ||
| title: Hostname routing | ||
| description: Learn how to route requests to the dispatch worker. | ||
| sidebar: | ||
| order: 3 | ||
| --- | ||
|
|
||
| import { Render, PackageManagers, WranglerConfig } from "~/components"; | ||
|
|
||
| You can use [dynamic dispatch](/cloudflare-for-platforms/workers-for-platforms/get-started/dynamic-dispatch/) Workers to route millions of vanity domains or subdomains to Workers without hitting traditional route limits. These hostnames can be subdomains under your managed domain (e.g. `customer1.saas.com`) or vanity domains controlled by your end customers (e.g. `mystore.com`), which can be managed through [custom hostnames](/cloudflare-for-platforms/cloudflare-for-saas/domain-support/). | ||
|
|
||
| ## (Recommended) Wildcard route with a dispatch Worker | ||
|
|
||
| Configure a wildcard [Route](/workers/configuration/routing/routes/) (`*/*`) on your SaaS domain (the domain where you configure custom hostnames) to point to your dynamic dispatch Worker. This allows you to: | ||
| - **Support both subdomains and vanity domains**: Handle `customer1.myplatform.com` (subdomain) and `shop.customer.com` (custom hostname) with the same routing logic. | ||
| - **Avoid route limits**: Instead of creating individual routes for every domain, which can cause you to hit [Routes limits](/workers/platform/limits/#number-of-routes-per-zone), you can handle the routing logic in code and proxy millions of domains to individual Workers. | ||
| - **Programmatically control routing logic**: Write custom code to route requests based on hostname, [custom metadata](/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/), path, or any other properties. | ||
|
|
||
| :::note | ||
| This will route all traffic inbound to the domain to the dispatch Worker. | ||
| ::: | ||
|
|
||
| If you'd like to exclude certain hostnames from routing to the dispatch Worker, you can either: | ||
| - Add routes without a Worker specification to opt certain hostnames or paths from being executed by the dispatcher Worker (for example, for `saas.com`, `api.saas.com`, etc) | ||
| - Use a [dedicated domain](/dns/zone-setups/subdomain-setup/) (for example, `customers.saas.com`) for custom hostname and dispatch worker management to keep the rest of the traffic for that domain separate. | ||
|
|
||
| ### Setup | ||
|
|
||
| To set up hostname routing with a wildcard route: | ||
|
|
||
| 1. **Configure custom hostnames**: Set up your domain and custom hostnames using [Cloudflare for SaaS](/cloudflare-for-platforms/cloudflare-for-saas/) | ||
| 2. **Set the fallback origin**: Set up a [fallback origin server](/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin), this is where all custom hostnames will be routed to. If you’d like to route them to separate origins, you can use a [custom origin server](/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/). Requests will route through the Worker before reaching the origin. If the Worker is the origin then place a dummy DNS record for the fallback origin (e.g., `A 192.0.2.0`). | ||
| 3. **Configure DNS**: Point DNS records (subdomains or custom hostname) via [CNAME record to the saas domain](/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record). If your customers need to proxy their apex hostname (e.g. `example.com`) and cannot use CNAME records, check out [Apex Proxying](/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/). | ||
| 4. **Create wildcard route**: Add a `*/*` route on your platform domain (e.g. saas.com) and associate it with your dispatch Worker. | ||
| 5. **Implement dispatch logic**: Add logic to your dispatch Worker to route based on hostname, lookup mappings stored in [Workers KV]([Workers KV](/kv/)), or use [custom metadata](/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) attached to custom hostnames. | ||
|
|
||
| :::note | ||
| If you plan to route requests based on custom metadata, you'll need to create subdomains (e.g. `customer1.saas.com`) as custom hostnames. This is because DNS records do not support custom metadata. | ||
| ::: | ||
|
|
||
| #### Example dispatch Worker | ||
|
|
||
| ```js | ||
| export default { | ||
| async fetch(request, env) { | ||
| const hostname = new URL(request.url).hostname; | ||
|
|
||
| // Get custom hostname metadata for routing decisions | ||
| const hostnameData = await env.KV.get(`hostname:${hostname}`, { type: 'json' }); | ||
|
|
||
| if (!hostnameData?.workerName) { | ||
| return new Response('Hostname not configured', { status: 404 }); | ||
| } | ||
|
|
||
| // Route to the appropriate user Worker | ||
| const userWorker = env.DISPATCHER.get(hostnameData.workerName); | ||
| return await userWorker.fetch(request); | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ## Subdomain routing | ||
|
|
||
| If you're only looking to route subdomain records (e.g. `customer1.saas.com`), you can use a more specific route (`*.saas.com/*`) to route requests to your dispatch Worker. | ||
|
|
||
| ### Setup | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. think accidentally commented out? or someting weird with format? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Set |
||
|
|
||
| To set up subdomain routing: | ||
|
|
||
| 1. Create an orange-clouded wildcard DNS record: `*.saas.com` that points to the origin. If the Worker is the origin then you can use a dummy DNS value (for example, `A 192.0.2.0`). | ||
| 2. Set wildcard route: `*.saas.com/*` pointing to your dispatch Worker | ||
| 3. Add logic to the dispatch Worker to route subdomain requests to the right Worker. | ||
|
|
||
| #### Example subdomain dispatch Worker | ||
|
|
||
| ```js | ||
| export default { | ||
| async fetch(request, env) { | ||
| const url = new URL(request.url); | ||
| const subdomain = url.hostname.split('.')[0]; | ||
|
|
||
| // Route based on subdomain | ||
| if (subdomain && subdomain !== 'saas') { | ||
| const userWorker = env.DISPATCHER.get(subdomain); | ||
| return await userWorker.fetch(request); | ||
| } | ||
|
|
||
| return new Response('Invalid subdomain', { status: 400 }); | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| ### Orange-to-Orange (o2o) Behavior | ||
|
|
||
| When your customers are also using Cloudflare and point their custom domain to your SaaS domain via CNAME (for example, `mystore.com` → `saas.com`), Worker routing behavior depends on whether the customer's DNS record is proxied (orange cloud) or DNS-only (grey cloud). Learn more about [Orange-to-Orange setups](/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/#with-o2o) | ||
|
|
||
| This can cause inconsistent behavior when using specific hostname routes: | ||
| - If you're routing based on the CNAME target (`saas.com`), the custom hostname's DNS record must be orange-clouded for the Worker to be invoked. | ||
| - If you're routing based on the custom hostname (`mystore.com`), the customer's record must be grey-clouded for the Worker to be invoked. | ||
|
|
||
| Since you may not have control over your customer's DNS proxy settings, we recommend using `*/*` wildcard route to ensure routing logic always works as expected, regardless of how DNS is configured. | ||
|
|
||
| #### Worker invocation across route configurations and proxy modes | ||
|
|
||
| The table below shows when Workers are invoked based on your route pattern and the customer's DNS proxy settings: | ||
|
|
||
| | Route Pattern | Custom Hostname (Orange Cloud) | Custom Hostname (Grey Cloud) | | ||
| |-----------------------|--------------|------------| | ||
| | `*/*` (Recommended) | ✅ | ✅ | | ||
| | Target hostname route | ✅ | ❌ | | ||
| | Custom hostname route | ❌ | ✅ | | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.