Initial commit
This commit is contained in:
309
skills/devops/references/cloudflare-workers-apis.md
Normal file
309
skills/devops/references/cloudflare-workers-apis.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Cloudflare Workers Runtime APIs
|
||||
|
||||
Key runtime APIs for Workers development.
|
||||
|
||||
## Fetch API
|
||||
|
||||
```typescript
|
||||
// Subrequest
|
||||
const response = await fetch('https://api.example.com/data', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ key: 'value' }),
|
||||
cf: {
|
||||
cacheTtl: 3600,
|
||||
cacheEverything: true
|
||||
}
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
```
|
||||
|
||||
## Headers API
|
||||
|
||||
```typescript
|
||||
// Read headers
|
||||
const userAgent = request.headers.get('User-Agent');
|
||||
|
||||
// Cloudflare-specific
|
||||
const country = request.cf?.country;
|
||||
const colo = request.cf?.colo;
|
||||
const clientIP = request.headers.get('CF-Connecting-IP');
|
||||
|
||||
// Set headers
|
||||
const headers = new Headers();
|
||||
headers.set('Content-Type', 'application/json');
|
||||
headers.append('X-Custom-Header', 'value');
|
||||
```
|
||||
|
||||
## HTMLRewriter
|
||||
|
||||
```typescript
|
||||
export default {
|
||||
async fetch(request: Request): Promise<Response> {
|
||||
const response = await fetch(request);
|
||||
|
||||
return new HTMLRewriter()
|
||||
.on('title', {
|
||||
element(element) {
|
||||
element.setInnerContent('New Title');
|
||||
}
|
||||
})
|
||||
.on('a[href]', {
|
||||
element(element) {
|
||||
const href = element.getAttribute('href');
|
||||
element.setAttribute('href', href.replace('http://', 'https://'));
|
||||
}
|
||||
})
|
||||
.transform(response);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## WebSockets
|
||||
|
||||
```typescript
|
||||
export default {
|
||||
async fetch(request: Request): Promise<Response> {
|
||||
const upgradeHeader = request.headers.get('Upgrade');
|
||||
if (upgradeHeader !== 'websocket') {
|
||||
return new Response('Expected WebSocket', { status: 426 });
|
||||
}
|
||||
|
||||
const pair = new WebSocketPair();
|
||||
const [client, server] = Object.values(pair);
|
||||
|
||||
server.accept();
|
||||
|
||||
server.addEventListener('message', (event) => {
|
||||
server.send(`Echo: ${event.data}`);
|
||||
});
|
||||
|
||||
return new Response(null, {
|
||||
status: 101,
|
||||
webSocket: client
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Streams API
|
||||
|
||||
```typescript
|
||||
const { readable, writable } = new TransformStream();
|
||||
|
||||
const writer = writable.getWriter();
|
||||
writer.write(new TextEncoder().encode('chunk 1'));
|
||||
writer.write(new TextEncoder().encode('chunk 2'));
|
||||
writer.close();
|
||||
|
||||
return new Response(readable, {
|
||||
headers: { 'Content-Type': 'text/plain' }
|
||||
});
|
||||
```
|
||||
|
||||
## Web Crypto API
|
||||
|
||||
```typescript
|
||||
// Generate hash
|
||||
const data = new TextEncoder().encode('message');
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
|
||||
// HMAC signature
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw',
|
||||
new TextEncoder().encode('secret'),
|
||||
{ name: 'HMAC', hash: 'SHA-256' },
|
||||
false,
|
||||
['sign', 'verify']
|
||||
);
|
||||
|
||||
const signature = await crypto.subtle.sign('HMAC', key, data);
|
||||
const valid = await crypto.subtle.verify('HMAC', key, signature, data);
|
||||
|
||||
// Random values
|
||||
const randomBytes = crypto.getRandomValues(new Uint8Array(32));
|
||||
const uuid = crypto.randomUUID();
|
||||
```
|
||||
|
||||
## Encoding APIs
|
||||
|
||||
```typescript
|
||||
// TextEncoder
|
||||
const encoder = new TextEncoder();
|
||||
const bytes = encoder.encode('Hello');
|
||||
|
||||
// TextDecoder
|
||||
const decoder = new TextDecoder();
|
||||
const text = decoder.decode(bytes);
|
||||
|
||||
// Base64
|
||||
const base64 = btoa('Hello');
|
||||
const decoded = atob(base64);
|
||||
```
|
||||
|
||||
## URL API
|
||||
|
||||
```typescript
|
||||
const url = new URL(request.url);
|
||||
const hostname = url.hostname;
|
||||
const pathname = url.pathname;
|
||||
const search = url.search;
|
||||
|
||||
// Query parameters
|
||||
const name = url.searchParams.get('name');
|
||||
url.searchParams.set('page', '2');
|
||||
url.searchParams.delete('old');
|
||||
```
|
||||
|
||||
## FormData API
|
||||
|
||||
```typescript
|
||||
// Parse form data
|
||||
const formData = await request.formData();
|
||||
const name = formData.get('name');
|
||||
const file = formData.get('file');
|
||||
|
||||
// Create form data
|
||||
const form = new FormData();
|
||||
form.append('name', 'value');
|
||||
form.append('file', blob, 'filename.txt');
|
||||
```
|
||||
|
||||
## Response Types
|
||||
|
||||
```typescript
|
||||
// Text
|
||||
return new Response('Hello');
|
||||
|
||||
// JSON
|
||||
return Response.json({ message: 'Hello' });
|
||||
|
||||
// Stream
|
||||
return new Response(readable);
|
||||
|
||||
// Redirect
|
||||
return Response.redirect('https://example.com', 302);
|
||||
|
||||
// Error
|
||||
return new Response('Not Found', { status: 404 });
|
||||
```
|
||||
|
||||
## Request Cloning
|
||||
|
||||
```typescript
|
||||
// Clone for multiple reads
|
||||
const clone = request.clone();
|
||||
const body1 = await request.json();
|
||||
const body2 = await clone.json();
|
||||
```
|
||||
|
||||
## AbortController
|
||||
|
||||
```typescript
|
||||
const controller = new AbortController();
|
||||
const { signal } = controller;
|
||||
|
||||
setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
try {
|
||||
const response = await fetch('https://slow-api.com', { signal });
|
||||
} catch (error) {
|
||||
if (error.name === 'AbortError') {
|
||||
console.log('Request timed out');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Scheduling APIs
|
||||
|
||||
```typescript
|
||||
// setTimeout
|
||||
const timeoutId = setTimeout(() => {
|
||||
console.log('Delayed');
|
||||
}, 1000);
|
||||
|
||||
// setInterval
|
||||
const intervalId = setInterval(() => {
|
||||
console.log('Repeated');
|
||||
}, 1000);
|
||||
|
||||
// Clear
|
||||
clearTimeout(timeoutId);
|
||||
clearInterval(intervalId);
|
||||
```
|
||||
|
||||
## Console API
|
||||
|
||||
```typescript
|
||||
console.log('Info message');
|
||||
console.error('Error message');
|
||||
console.warn('Warning message');
|
||||
console.debug('Debug message');
|
||||
|
||||
// Structured logging
|
||||
console.log(JSON.stringify({
|
||||
level: 'info',
|
||||
message: 'Request processed',
|
||||
url: request.url,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
```
|
||||
|
||||
## Performance API
|
||||
|
||||
```typescript
|
||||
const start = performance.now();
|
||||
await processRequest();
|
||||
const duration = performance.now() - start;
|
||||
console.log(`Processed in ${duration}ms`);
|
||||
```
|
||||
|
||||
## Bindings Reference
|
||||
|
||||
### KV Operations
|
||||
```typescript
|
||||
await env.KV.put(key, value, { expirationTtl: 3600, metadata: { userId: '123' } });
|
||||
const value = await env.KV.get(key, 'json');
|
||||
const { value, metadata } = await env.KV.getWithMetadata(key);
|
||||
await env.KV.delete(key);
|
||||
const list = await env.KV.list({ prefix: 'user:' });
|
||||
```
|
||||
|
||||
### D1 Operations
|
||||
```typescript
|
||||
const result = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();
|
||||
const { results } = await env.DB.prepare('SELECT * FROM users').all();
|
||||
await env.DB.prepare('INSERT INTO users (name) VALUES (?)').bind(name).run();
|
||||
await env.DB.batch([stmt1, stmt2, stmt3]);
|
||||
```
|
||||
|
||||
### R2 Operations
|
||||
```typescript
|
||||
await env.R2.put(key, value, { httpMetadata: { contentType: 'image/jpeg' } });
|
||||
const object = await env.R2.get(key);
|
||||
await env.R2.delete(key);
|
||||
const list = await env.R2.list({ prefix: 'uploads/' });
|
||||
const multipart = await env.R2.createMultipartUpload(key);
|
||||
```
|
||||
|
||||
### Queue Operations
|
||||
```typescript
|
||||
await env.QUEUE.send({ type: 'email', to: 'user@example.com' });
|
||||
await env.QUEUE.sendBatch([{ body: msg1 }, { body: msg2 }]);
|
||||
```
|
||||
|
||||
### Workers AI
|
||||
```typescript
|
||||
const response = await env.AI.run('@cf/meta/llama-3-8b-instruct', {
|
||||
messages: [{ role: 'user', content: 'What is edge computing?' }]
|
||||
});
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- Runtime APIs: https://developers.cloudflare.com/workers/runtime-apis/
|
||||
- Web Standards: https://developers.cloudflare.com/workers/runtime-apis/web-standards/
|
||||
- Bindings: https://developers.cloudflare.com/workers/runtime-apis/bindings/
|
||||
Reference in New Issue
Block a user