Prompting·续1
<key_points>
- Uses Hono as the router and middleware
- Uses Workers KV to store session data
- Uses the Authorization header or Cookie to get the token
- Checks the token in Workers KV
- Returns a 403 if the token is invalid or expired
</key_points> </example>
<example id="queue_producer_consumer_example"> <description> Use Cloudflare Queues to produce and consume messages. </description>
<code language="typescript"> // src/producer.ts interface Env { REQUEST_QUEUE: Queue; UPSTREAM_API_URL: string; UPSTREAM_API_KEY: string; }
export default { async fetch(request: Request, env: Env) { const info = { timestamp: new Date().toISOString(), method: request.method, url: request.url, headers: Object.fromEntries(request.headers), }; await env.REQUEST_QUEUE.send(info);
return Response.json({ message: 'Request logged', requestId: crypto.randomUUID() });
},
async queue(batch: MessageBatch<any>, env: Env) { const requests = batch.messages.map(msg => msg.body);
const response = await fetch(env.UPSTREAM_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${env.UPSTREAM_API_KEY}
},
body: JSON.stringify({
timestamp: new Date().toISOString(),
batchSize: requests.length,
requests
})
});
if (!response.ok) {
throw new Error(Upstream API error: ${response.status});
}
} };
</code>
<configuration> { "name": "request-logger-consumer", "main": "src/index.ts", "compatibility_date": "2025-02-11", "queues": { "producers": [{ "name": "request-queue", "binding": "REQUEST_QUEUE" }], "consumers": [{ "name": "request-queue", "dead_letter_queue": "request-queue-dlq", "retry_delay": 300 }] }, "vars": { "UPSTREAM_API_URL": "https://api.example.com/batch-logs", "UPSTREAM_API_KEY": "" } } </configuration>
<key_points>
- Defines both a producer and consumer for the queue
- Uses a dead letter queue for failed messages
- Uses a retry delay of 300 seconds to delay the re-delivery of failed messages
- Shows how to batch requests to an upstream API
</key_points> </example>
<example id="hyperdrive_connect_to_postgres"> <description> Connect to and query a Postgres database using Cloudflare Hyperdrive. </description>
<code language="typescript"> // Postgres.js 3.4.5 or later is recommended import postgres from "postgres";
export interface Env { // If you set another name in the Wrangler config file as the value for 'binding', // replace "HYPERDRIVE" with the variable name you defined. HYPERDRIVE: Hyperdrive; }
export default { async fetch(request, env, ctx): Promise<Response> { console.log(JSON.stringify(env)); // Create a database client that connects to your database via Hyperdrive. // // Hyperdrive generates a unique connection string you can pass to // supported drivers, including node-postgres, Postgres.js, and the many // ORMs and query builders that use these drivers. const sql = postgres(env.HYPERDRIVE.connectionString)
try {
// Test query
const results = await sqlSELECT * FROM pg_tables;
// Return result rows as JSON return Response.json(results); } catch (e) { console.error(e); return Response.json( { error: e instanceof Error ? e.message : e }, { status: 500 }, ); }
}, } satisfies ExportedHandler<Env>;
</code>
<configuration> { "name": "hyperdrive-postgres", "main": "src/index.ts", "compatibility_date": "2025-02-11", "hyperdrive": [ { "binding": "HYPERDRIVE", "id": "<YOUR_DATABASE_ID>" } ] } </configuration>
<usage> // Install Postgres.js npm install postgres
// Create a Hyperdrive configuration npx wrangler hyperdrive create <YOUR_CONFIG_NAME> --connection-string="postgres://user:password@HOSTNAME_OR_IP_ADDRESS:PORT/database_name"
</usage>
<key_points>
- Installs and uses Postgres.js as the database client/driver.
- Creates a Hyperdrive configuration using wrangler and the database connection string.
- Uses the Hyperdrive connection string to connect to the database.
- Calling
sql.end()is optional, as Hyperdrive will handle the connection pooling.
</key_points> </example>
<example id="workflows"> <description> Using Workflows for durable execution, async tasks, and human-in-the-loop workflows. </description>
<code language="typescript"> import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers';
type Env = { // Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. MY_WORKFLOW: Workflow; };
// User-defined params passed to your workflow type Params = { email: string; metadata: Record<string, string>; };
export class MyWorkflow extends WorkflowEntrypoint<Env, Params> {
async run(event: WorkflowEvent<Params>, step: WorkflowStep) {
// Can access bindings on this.env
// Can access params on event.payload
const files = await step.do('my first step', async () => {
// Fetch a list of files from $SOME_SERVICE
return {
files: [
'doc_7392_rev3.pdf',
'report_x29_final.pdf',
'memo_2024_05_12.pdf',
'file_089_update.pdf',
'proj_alpha_v2.pdf',
'data_analysis_q2.pdf',
'notes_meeting_52.pdf',
'summary_fy24_draft.pdf',
],
};
});
const apiResponse = await step.do('some other step', async () => { let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); return await resp.json<any>(); });
await step.sleep('wait on something', '1 minute');
await step.do( 'make a call to write that could maybe, just might, fail', // Define a retry strategy { retries: { limit: 5, delay: '5 second', backoff: 'exponential', }, timeout: '15 minutes', }, async () => { // Do stuff here, with access to the state from our previous steps if (Math.random() > 0.5) { throw new Error('API call to $STORAGE_SYSTEM failed'); } }, );
} }
export default { async fetch(req: Request, env: Env): Promise<Response> { let url = new URL(req.url);
if (url.pathname.startsWith('/favicon')) { return Response.json({}, { status: 404 }); }
// Get the status of an existing instance, if provided let id = url.searchParams.get('instanceId'); if (id) { let instance = await env.MY_WORKFLOW.get(id); return Response.json({ status: await instance.status(), }); }
const data = await req.json()
// Spawn a new instance and return the ID and status let instance = await env.MY_WORKFLOW.create({ // Define an ID for the Workflow instance id: crypto.randomUUID(), // Pass data to the Workflow instance // Available on the WorkflowEvent params: data, });
return Response.json({ id: instance.id, details: await instance.status(), });
}, };
</code>
<configuration> { "name": "workflows-starter", "main": "src/index.ts", "compatibility_date": "2025-02-11", "workflows": [ { "name": "workflows-starter", "binding": "MY_WORKFLOW", "class_name": "MyWorkflow" } ] } </configuration>
<key_points>
- Defines a Workflow by extending the WorkflowEntrypoint class.
- Defines a run method on the Workflow that is invoked when the Workflow is started.
- Ensures that
awaitis used before callingstep.doorstep.sleep - Passes a payload (event) to the Workflow from a Worker
- Defines a payload type and uses TypeScript type arguments to ensure type safety
</key_points> </example>
<example id="workers_analytics_engine"> <description> Using Workers Analytics Engine for writing event data. </description>
<code language="typescript"> interface Env { USER_EVENTS: AnalyticsEngineDataset; }
export default { async fetch(req: Request, env: Env): Promise<Response> { let url = new URL(req.url); let path = url.pathname; let userId = url.searchParams.get("userId");
// Write a datapoint for this visit, associating the data with // the userId as our Analytics Engine 'index' env.USER_EVENTS.writeDataPoint({ // Write metrics data: counters, gauges or latency statistics doubles: [], // Write text labels - URLs, app names, event_names, etc blobs: [path], // Provide an index that groups your data correctly. indexes: [userId], });
return Response.json({ hello: "world", }); ,
};
</code>
<configuration> { "name": "analytics-engine-example", "main": "src/index.ts", "compatibility_date": "2025-02-11", "analytics_engine_datasets": [ { "binding": "<BINDING_NAME>", "dataset": "<DATASET_NAME>" } ] } } </configuration>
<usage> // Query data within the 'temperatures' dataset // This is accessible via the REST API at https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql SELECT timestamp, blob1 AS location_id, double1 AS inside_temp, double2 AS outside_temp FROM temperatures WHERE timestamp > NOW() - INTERVAL '1' DAY
// List the datasets (tables) within your Analytics Engine curl "<https://api.cloudflare.com/client/v4/accounts/{account_id}/analytics_engine/sql>" \ --header "Authorization: Bearer <API_TOKEN>" \ --data "SHOW TABLES"
</usage>
<key_points>
- Binds an Analytics Engine dataset to the Worker
- Uses the
AnalyticsEngineDatasettype when using TypeScript for the binding - Writes event data using the
writeDataPointmethod and writes anAnalyticsEngineDataPoint - Does NOT
awaitcalls towriteDataPoint, as it is non-blocking - Defines an index as the key representing an app, customer, merchant or tenant.
- Developers can use the GraphQL or SQL APIs to query data written to Analytics Engine </key_points> </example>
<example id="browser_rendering_workers"> <description> Use the Browser Run API (formerly Browser Rendering API) as a headless browser to interact with websites from a Cloudflare Worker. </description>
<code language="typescript"> import puppeteer from "@cloudflare/puppeteer";
interface Env { BROWSER_RENDERING: Fetcher; }
export default { async fetch(request, env): Promise<Response> { const { searchParams } = new URL(request.url); let url = searchParams.get("url");
if (url) { url = new URL(url).toString(); // normalize const browser = await puppeteer.launch(env.MYBROWSER); const page = await browser.newPage(); await page.goto(url); // Parse the page content const content = await page.content(); // Find text within the page content const text = await page.$eval("body", (el) => el.textContent); // Do something with the text // e.g. log it to the console, write it to KV, or store it in a database. console.log(text);
// Ensure we close the browser session await browser.close();
return Response.json({ bodyText: text, }) } else { return Response.json({ error: "Please add an ?url=https://example.com/ parameter" }, { status: 400 }) } }, } satisfies ExportedHandler<Env>; </code>
<configuration> { "name": "browser-rendering-example", "main": "src/index.ts", "compatibility_date": "2025-02-11", "browser": [ { "binding": "BROWSER_RENDERING", } ] } </configuration>
<usage> // Install @cloudflare/puppeteer npm install @cloudflare/puppeteer --save-dev </usage>
<key_points>
- Configures a BROWSER_RENDERING binding
- Passes the binding to Puppeteer
- Uses the Puppeteer APIs to navigate to a URL and render the page
- Parses the DOM and returns context for use in the response
- Correctly creates and closes the browser instance
</key_points> </example>
<example id="static-assets"> <description> Serve Static Assets from a Cloudflare Worker and/or configure a Single Page Application (SPA) to correctly handle HTTP 404 (Not Found) requests and route them to the entrypoint. </description> <code language="typescript"> // src/index.ts
interface Env { ASSETS: Fetcher; }
export default { fetch(request, env) { const url = new URL(request.url);
if (url.pathname.startsWith("/api/")) { return Response.json({ name: "Cloudflare", }); }
return env.ASSETS.fetch(request); }, } satisfies ExportedHandler<Env>; </code> <configuration> { "name": "my-app", "main": "src/index.ts", "compatibility_date": "<TBD>", "assets": { "directory": "./public/", "not_found_handling": "single-page-application", "binding": "ASSETS" }, "observability": { "enabled": true } } </configuration> <key_points> - Configures a ASSETS binding - Uses /public/ as the directory the build output goes to from the framework of choice - The Worker will handle any requests that a path cannot be found for and serve as the API - If the application is a single-page application (SPA), HTTP 404 (Not Found) requests will direct to the SPA.
</key_points> </example>
<example id="agents"> <code language="typescript"> <description> Build an AI Agent on Cloudflare Workers, using the agents, and the state management and syncing APIs built into the agents. </description>
<code language="typescript"> // src/index.ts import { Agent, AgentNamespace, Connection, ConnectionContext, getAgentByName, routeAgentRequest, WSMessage } from 'agents'; import { OpenAI } from "openai";
interface Env { AIAgent: AgentNamespace<Agent>; OPENAI_API_KEY: string; }
export class AIAgent extends Agent { // Handle HTTP requests with your Agent async onRequest(request) { // Connect with AI capabilities const ai = new OpenAI({ apiKey: this.env.OPENAI_API_KEY, });
// Process and understand const response = await ai.chat.completions.create({ model: "gpt-4", messages: [{ role: "user", content: await request.text() }], });
return new Response(response.choices[0].message.content); }
async processTask(task) { await this.understand(task); await this.act(); await this.reflect(); }
// Handle WebSockets async onConnect(connection: Connection) { await this.initiate(connection); connection.accept() }
async onMessage(connection, message) { const understanding = await this.comprehend(message); await this.respond(connection, understanding); }
async evolve(newInsight) { this.setState({ ...this.state, insights: [...(this.state.insights || []), newInsight], understanding: this.state.understanding + 1, }); }
onStateUpdate(state, source) { console.log("Understanding deepened:", { newState: state, origin: source, }); }
// Scheduling APIs // An Agent can schedule tasks to be run in the future by calling this.schedule(when, callback, data), where when can be a delay, a Date, or a cron string; callback the function name to call, and data is an object of data to pass to the function. // // Scheduled tasks can do anything a request or message from a user can: make requests, query databases, send emails, read+write state: scheduled tasks can invoke any regular method on your Agent. async scheduleExamples() { // schedule a task to run in 10 seconds let task = await this.schedule(10, "someTask", { message: "hello" });
// schedule a task to run at a specific date let task = await this.schedule(new Date("2025-01-01"), "someTask", {});
// schedule a task to run every 10 seconds let { id } = await this.schedule("/10 * * * ", "someTask", { message: "hello" });
// schedule a task to run every 10 seconds, but only on Mondays let task = await this.schedule("0 0 * * 1", "someTask", { message: "hello" });
// cancel a scheduled task this.cancelSchedule(task.id);
// Get a specific schedule by ID // Returns undefined if the task does not exist let task = await this.getSchedule(task.id)
// Get all scheduled tasks // Returns an array of Schedule objects let tasks = this.getSchedules();
// Cancel a task by its ID // Returns true if the task was cancelled, false if it did not exist await this.cancelSchedule(task.id);
// Filter for specific tasks // e.g. all tasks starting in the next hour let tasks = this.getSchedules({ timeRange: { start: new Date(Date.now()), end: new Date(Date.now() + 60 * 60 * 1000), } }); }
