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 await is used before calling step.do or step.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 AnalyticsEngineDataset type when using TypeScript for the binding
  • Writes event data using the writeDataPoint method and writes an AnalyticsEngineDataPoint
  • Does NOT await calls to writeDataPoint, 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), } }); }