Skip to content
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

Tweak ExportedHandler types to improve DX #14007

Merged
merged 10 commits into from
Apr 23, 2024
12 changes: 6 additions & 6 deletions content/r2/api/s3/presigned-urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ pcx_content_type: concept

Presigned URLs are an [S3 concept](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) for sharing direct access to your bucket without revealing your token secret. A presigned URL authorizes anyone with the URL to perform an action to the S3 compatibility endpoint for an R2 bucket. By default, the S3 endpoint requires an `AUTHORIZATION` header signed by your token. Every presigned URL has S3 parameters and search parameters containing the signature information that would be present in an `AUTHORIZATION` header. The performable action is restricted to a specific resource, an [operation](/r2/api/s3/api/), and has an associated timeout.

There are three kinds of resources in R2:
There are three kinds of resources in R2:

1. **Account**: For account-level operations (such as `CreateBucket`, `ListBuckets`, `DeleteBucket`) the identifier is the account ID.
2. **Bucket**: For bucket-level operations (such as `ListObjects`, `PutBucketCors`) the identifier is the account ID, and bucket name.
3. **Object**: For object-level operations (such as `GetObject`, `PutObject`, `CreateMultipartUpload`) the identifier is the account ID, bucket name, and object path.

All parts of the identifier are part of the presigned URL.
All parts of the identifier are part of the presigned URL.

You cannot change the resource being accessed after the request is signed. For example, trying to change the bucket name to access the same object in a different bucket will return a `403` with an error code of `SignatureDoesNotMatch`.

Expand All @@ -29,9 +29,9 @@ There are three ways to grant an application access to R2:
2. The application requests a copy of an R2 API token from a vault application and promises to not permanently store that token locally.
3. The application requests a central application to give it a presigned URL it can use to perform an action.

In scenarios 1 and 2, if the application or vault application is compromised, the holder of the token can perform arbitrary actions.
In scenarios 1 and 2, if the application or vault application is compromised, the holder of the token can perform arbitrary actions.

Scenario 3 keeps the credential secret. If the application making a presigned URL request to the central application leaks that URL, but the central application does not have its key storage system compromised, the impact is limited to one operation on the specific resource that was signed.
Scenario 3 keeps the credential secret. If the application making a presigned URL request to the central application leaks that URL, but the central application does not have its key storage system compromised, the impact is limited to one operation on the specific resource that was signed.

Additionally, the central application can perform monitoring, auditing, logging tasks so you can review when a request was made to perform an operation on a specific resource. In the event of a security incident, you can use a central application's logging functionality to review details of the incident.

Expand Down Expand Up @@ -86,8 +86,8 @@ const r2 = new AwsClient({
secretAccessKey: "",
});

export default <ExportedHandler>{
async fetch(req) {
export default {
async fetch(req: Request): Promise<Response> {
// This is just an example to demonstrating using aws4fetch to generate a presigned URL.
// This Worker should not be used as-is as it does not authenticate the request, meaning
// that anyone can upload to your bucket.
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/103-early-hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const HTML = `
`;

export default {
async fetch(req) {
async fetch(req: Request): Promise<Response> {
// If request is for test.css, serve the raw CSS
if (/test\.css$/.test(req.url)) {
return new Response(CSS, {
Expand All @@ -105,7 +105,7 @@ export default {
});
}
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/ab-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export default {
const NAME = "myExampleWorkersABTest";

export default {
async fetch(req) {
async fetch(req: Request): Promise<Response> {
const url = new URL(req.url);
// Enable Passthrough to allow direct access to control and test routes.
if (url.pathname.startsWith("/control") || url.pathname.startsWith("/test"))
Expand Down Expand Up @@ -87,7 +87,7 @@ export default {
}
return fetch(url);
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/accessing-the-cloudflare-object.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default {

```ts
export default {
async fetch(req) {
async fetch(req: Request): Promise<Response> {
const data =
req.cf !== undefined
? req.cf
Expand All @@ -51,7 +51,7 @@ export default {
},
});
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/aggregate-requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
/**
* someHost is set up to return JSON responses
* Replace url1 and url2 with the hosts you wish to send requests to
Expand Down Expand Up @@ -109,7 +109,7 @@ export default {
]);
return new Response(results.join(), init);
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/alter-headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
const response = await fetch(request);

// Clone the response so that it's no longer immutable
Expand All @@ -68,7 +68,7 @@ export default {
newResponse.headers.set("x-header-to-change", "NewValue");
return newResponse;
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/auth-with-headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
/**
* @param {string} PRESHARED_AUTH_HEADER_KEY Custom header to check for key
* @param {string} PRESHARED_AUTH_HEADER_VALUE Hard coded key value
Expand All @@ -70,7 +70,7 @@ export default {
status: 403,
});
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
7 changes: 5 additions & 2 deletions content/workers/examples/basic-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,11 @@ function timingSafeEqual(a: string, b: string) {
return crypto.subtle.timingSafeEqual(aBytes, bBytes);
}

interface Env {
PASSWORD: string;
}
export default {
async fetch(request, env) {
async fetch(request: Request, env: Env): Promise<Response> {
const BASIC_USER = "admin";

// You will need an admin password. This should be
Expand Down Expand Up @@ -250,7 +253,7 @@ export default {

return new Response("Not Found.", { status: 404 });
},
} satisfies ExportedHandler<{ PASSWORD: string }>;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/block-on-tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default {

```ts
export default {
async fetch(request: Request) {
async fetch(request: Request): Promise<Response> {
try {
const tlsVersion = request.cf.tlsVersion;
// Allow only TLS versions 1.2 and 1.3
Expand All @@ -61,7 +61,7 @@ export default {
});
}
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/bulk-origin-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default {

```ts
export default {
async fetch(request: Request) {
async fetch(request: Request): Promise<Response> {
/**
* An object with different URLs to fetch
* @param {Object} ORIGINS
Expand All @@ -66,7 +66,7 @@ export default {
// Otherwise, process request as normal
return fetch(request);
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/bulk-redirects.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
const externalHostname = "examples.cloudflareworkers.com";

const redirectMap = new Map([
Expand All @@ -63,7 +63,7 @@ export default {
// If request not in map, return the original request
return fetch(request);
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
5 changes: 3 additions & 2 deletions content/workers/examples/cache-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ export default {
{{<tab label="ts">}}

```ts
interface Env {}
export default {
async fetch(request, env, ctx) {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const cacheUrl = new URL(request.url);

// Construct the cache key from the cache URL
Expand Down Expand Up @@ -90,7 +91,7 @@ export default {
}
return response;
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
5 changes: 3 additions & 2 deletions content/workers/examples/cache-post-request.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ export default {
{{<tab label="ts">}}

```ts
interface Env {}
export default {
async fetch(request, env, ctx) {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
async function sha256(message) {
// encode as UTF-8
const msgBuffer = await new TextEncoder().encode(message);
Expand Down Expand Up @@ -104,7 +105,7 @@ export default {
return new Response("Error thrown " + e.message);
}
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/cache-tags.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
const requestUrl = new URL(request.url);
const params = requestUrl.searchParams;
const tags =
Expand Down Expand Up @@ -97,7 +97,7 @@ export default {
return new Response(JSON.stringify(errorObject), { status: 500 });
});
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
8 changes: 4 additions & 4 deletions content/workers/examples/cache-using-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request) {
const url = new URL(request.url);
// Only use the path for the cache key, removing query strings
// and always store using HTTPS, for example, https://www.example.com/file-uri-here
Expand All @@ -67,7 +67,7 @@ export default {
response.headers.set("Cache-Control", "max-age=1500");
return response;
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down Expand Up @@ -130,7 +130,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
let url = new URL(request.url);

if (Math.random() < 0.5) {
Expand All @@ -144,7 +144,7 @@ export default {
cf: { cacheKey: request.url },
});
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/conditional-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
const BLOCKED_HOSTNAMES = ["nope.mywebsite.com", "bye.website.com"];
// Return a new Response based on a URL's hostname
const url = new URL(request.url);
Expand Down Expand Up @@ -107,7 +107,7 @@ export default {
);
return fetch(request);
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/cors-header-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS",
Expand Down Expand Up @@ -319,7 +319,7 @@ export default {
return rawHtmlResponse(DEMO_PAGE);
}
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
4 changes: 2 additions & 2 deletions content/workers/examples/country-code-redirect.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default {

```ts
export default {
async fetch(request) {
async fetch(request: Request): Promise<Response> {
/**
* A map of the URLs to redirect to
* @param {Object} countryMap
Expand All @@ -69,7 +69,7 @@ export default {
return fetch(request);
}
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
Expand Down
7 changes: 4 additions & 3 deletions content/workers/examples/cron-trigger.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,20 @@ export default {
{{<tab label="ts">}}

```ts
interface Env {}
export default {
async scheduled(event, env, ctx) {
async scheduled(controller: ScheduledController, env: Env, ctx: ExecutionContext) {
console.log("cron processed");
},
} satisfies ExportedHandler;
};
```

{{</tab>}}
{{</tabs>}}

## Set Cron Triggers in Wrangler

Refer to [Cron Triggers](/workers/configuration/cron-triggers/) for more information on how to add a Cron Trigger.
Refer to [Cron Triggers](/workers/configuration/cron-triggers/) for more information on how to add a Cron Trigger.

If you are deploying with Wrangler, set the cron syntax (once per hour as shown below) by adding this to your `wrangler.toml` file:

Expand Down
Loading
Loading