Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
83 changes: 83 additions & 0 deletions platform/src/components/cloudflare/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from "path";
import crypto from "crypto";
import {
ComponentResourceOptions,
Output,
output,
all,
jsonStringify,
Expand Down Expand Up @@ -66,6 +67,44 @@ export interface WorkerArgs {
* ```
*/
domain?: Input<string>;
/**
* Attach the Worker to one or more [route patterns](https://developers.cloudflare.com/workers/configuration/routing/routes/)
* instead of a dedicated custom domain.
*
* Unlike `domain`, which gives the Worker a full hostname, routes are
* pattern-based. This lets multiple Workers (or a Pages project) share a
* hostname and fall through to the origin for unmatched paths. Use routes
* when you want to put a Worker in front of only part of a site, e.g.
* `example.com/api/*`.
*
* Each pattern must start with a concrete hostname that belongs to a
* Cloudflare zone on the same account. Wildcard hostnames like `*.example.com`
* are not supported here.
*
* A proxied DNS record for the hostname must already exist in the zone —
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as i'm learning more about this routes feature, i'm thinking whether it's a good idea to automatically create the DNS record for the user

if we don't, probably we should add an example of how to do it. ideally, we would create it, but i guess if you have multiple workers, that defeats the purpose

maybe you're more familiar and have a clear idea of how to deal with this

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any ideas @Makisuo?

for the recent redirects features we are creating the record

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry completely missed the previous comments, Github Notifications are a bit broken for me currently.
Think it makes sense if we automatically create a DNS record if not already existing.

Have often seen people be confused why routes weren't working since this pattern isn't quite clear anyways, so this makes a lot of sense

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great! if you add that, i will merge the pr

ideally, also attach some screenshots/video of it working

* routes do not auto-manage DNS, unlike custom domains. You can create
* one in the Cloudflare dashboard or alongside the Worker with a
* `cloudflare.DnsRecord` resource.
*
* Cannot be used together with `domain`.
*
* @example
*
* ```js
* {
* routes: ["example.com/api/*"]
* }
* ```
*
* Multiple patterns on the same Worker:
*
* ```js
* {
* routes: ["example.com/api/*", "api.example.com/*"]
* }
* ```
*/
routes?: Input<Input<string>[]>;
Comment thread
Makisuo marked this conversation as resolved.
Outdated
/**
* Configure how your function is bundled.
*
Expand Down Expand Up @@ -294,6 +333,7 @@ export class Worker extends Component implements Link.Linkable {
private workerUrl: WorkerUrl;
private workerPlacement?: WorkerPlacement;
private workerDomain?: cf.WorkerDomain;
private workerRoutes?: Output<cf.WorkersRoute[]>;

constructor(name: string, args: WorkerArgs, opts?: ComponentResourceOptions) {
super(__pulumiType, name, args, opts);
Expand Down Expand Up @@ -324,11 +364,13 @@ export class Worker extends Component implements Link.Linkable {
const workerUrl = createWorkersUrl();
const workerPlacement = createWorkerPlacement();
const workerDomain = createWorkersDomain();
const workerRoutes = createWorkersRoutes();

this.script = script;
this.workerUrl = workerUrl;
this.workerPlacement = workerPlacement;
this.workerDomain = workerDomain;
this.workerRoutes = workerRoutes;

all([dev, buildInput, script.scriptName]).apply(
async ([dev, buildInput, scriptName]) => {
Expand Down Expand Up @@ -619,6 +661,43 @@ export class Worker extends Component implements Link.Linkable {
{ parent },
);
}

function createWorkersRoutes() {
if (!args.routes) return;
if (args.domain)
throw new VisibleError(
`Cannot set both "domain" and "routes" on the "${name}" Worker. Use "domain" for a dedicated hostname, or "routes" for pattern-based routing.`,
);

return output(args.routes).apply((patterns) =>
Comment thread
Makisuo marked this conversation as resolved.
Outdated
patterns.map((pattern, i) => {
const hostname = pattern.split("/")[0];
if (!hostname || hostname.includes("*"))
throw new VisibleError(
`Route pattern "${pattern}" on the "${name}" Worker must start with a concrete hostname (e.g. "example.com/*"). Wildcard hostnames are not supported.`,
);

const zone = new ZoneLookup(
`${name}Route${i}ZoneLookup`,
{
accountId: DEFAULT_ACCOUNT_ID,
domain: hostname,
},
{ parent },
);

return new cf.WorkersRoute(
`${name}Route${i}`,
{
zoneId: zone.id,
pattern,
script: script.scriptName,
},
{ parent },
);
}),
);
}
}

/**
Expand All @@ -639,6 +718,10 @@ export class Worker extends Component implements Link.Linkable {
* The Cloudflare Worker script.
*/
worker: this.script,
/**
* The Cloudflare Worker routes, if `routes` was set.
*/
routes: this.workerRoutes,
};
}

Expand Down
1 change: 1 addition & 0 deletions platform/src/components/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ export class Component extends ComponentResource {
"cloudflare:index/dnsRecord:DnsRecord",
"cloudflare:index/workersCronTrigger:WorkersCronTrigger",
"cloudflare:index/workersCustomDomain:WorkersCustomDomain",
"cloudflare:index/workersRoute:WorkersRoute",
"cloudflare:index/queueConsumer:QueueConsumer",
"docker-build:index:Image",
"vercel:index/dnsRecord:DnsRecord",
Expand Down
Loading