mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 18:11:27 -07:00
update skills
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
# Cloudflare Snippets Skill Reference
|
||||
|
||||
## Description
|
||||
Expert guidance for **Cloudflare Snippets ONLY** - a lightweight JavaScript-based edge logic platform for modifying HTTP requests and responses. Snippets run as part of the Ruleset Engine and are included at no additional cost on paid plans (Pro, Business, Enterprise).
|
||||
|
||||
## What Are Snippets?
|
||||
Snippets are JavaScript functions executed at the edge as part of Cloudflare's Ruleset Engine. Key characteristics:
|
||||
- **Execution time**: 5ms CPU limit per request
|
||||
- **Size limit**: 32KB per snippet
|
||||
- **Runtime**: V8 isolate (subset of Workers APIs)
|
||||
- **Subrequests**: 2-5 fetch calls depending on plan
|
||||
- **Cost**: Included with Pro/Business/Enterprise plans
|
||||
|
||||
## Snippets vs Workers Decision Matrix
|
||||
|
||||
| Factor | Choose Snippets If... | Choose Workers If... |
|
||||
|--------|----------------------|---------------------|
|
||||
| **Complexity** | Simple request/response modifications | Complex business logic, routing, middleware |
|
||||
| **Execution time** | <5ms sufficient | Need >5ms or variable time |
|
||||
| **Subrequests** | 2-5 fetch calls sufficient | Need >5 subrequests or complex orchestration |
|
||||
| **Code size** | <32KB sufficient | Need >32KB or npm dependencies |
|
||||
| **Cost** | Want zero additional cost | Can afford $5/mo + usage |
|
||||
| **APIs** | Need basic fetch, headers, URL | Need KV, D1, R2, Durable Objects, cron triggers |
|
||||
| **Deployment** | Need rule-based triggers | Want custom routing logic |
|
||||
|
||||
**Rule of thumb**: Use Snippets for modifications, Workers for applications.
|
||||
|
||||
## Execution Model
|
||||
1. Request arrives at Cloudflare edge
|
||||
2. Ruleset Engine evaluates snippet rules (filter expressions)
|
||||
3. If rule matches, snippet executes within 5ms limit
|
||||
4. Modified request/response continues through pipeline
|
||||
5. Response returned to client
|
||||
|
||||
Snippets execute synchronously in the request path - performance is critical.
|
||||
|
||||
## Reading Order
|
||||
1. **[configuration.md](configuration.md)** - Start here: setup, deployment methods (Dashboard/API/Terraform)
|
||||
2. **[api.md](api.md)** - Core APIs: Request, Response, headers, `request.cf` properties
|
||||
3. **[patterns.md](patterns.md)** - Real-world examples: geo-routing, A/B tests, security headers
|
||||
4. **[gotchas.md](gotchas.md)** - Troubleshooting: common errors, performance tips, API limitations
|
||||
|
||||
## In This Reference
|
||||
|
||||
- **[configuration.md](configuration.md)** - Setup, deployment, configuration
|
||||
- **[api.md](api.md)** - API endpoints, methods, interfaces
|
||||
- **[patterns.md](patterns.md)** - Common patterns, use cases, examples
|
||||
- **[gotchas.md](gotchas.md)** - Troubleshooting, best practices, limitations
|
||||
|
||||
## Quick Start
|
||||
```javascript
|
||||
// Snippet: Add security headers
|
||||
export default {
|
||||
async fetch(request) {
|
||||
const response = await fetch(request);
|
||||
const newResponse = new Response(response.body, response);
|
||||
newResponse.headers.set("X-Frame-Options", "DENY");
|
||||
newResponse.headers.set("X-Content-Type-Options", "nosniff");
|
||||
return newResponse;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Deploy via Dashboard (Rules → Snippets) or API/Terraform. See configuration.md for details.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Cloudflare Docs](https://developers.cloudflare.com/rules/snippets/)
|
||||
198
.agents/skills/cloudflare-deploy/references/snippets/api.md
Normal file
198
.agents/skills/cloudflare-deploy/references/snippets/api.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Snippets API Reference
|
||||
|
||||
## Request Object
|
||||
|
||||
### HTTP Properties
|
||||
```javascript
|
||||
request.method // GET, POST, PUT, DELETE, etc.
|
||||
request.url // Full URL string
|
||||
request.headers // Headers object
|
||||
request.body // ReadableStream (for POST/PUT)
|
||||
request.cf // Cloudflare properties (see below)
|
||||
```
|
||||
|
||||
### URL Operations
|
||||
```javascript
|
||||
const url = new URL(request.url);
|
||||
url.hostname // "example.com"
|
||||
url.pathname // "/path/to/page"
|
||||
url.search // "?query=value"
|
||||
url.searchParams.get("q") // "value"
|
||||
url.searchParams.set("q", "new")
|
||||
url.searchParams.delete("q")
|
||||
```
|
||||
|
||||
### Header Operations
|
||||
```javascript
|
||||
// Read headers
|
||||
request.headers.get("User-Agent")
|
||||
request.headers.has("Authorization")
|
||||
request.headers.getSetCookie() // Get all Set-Cookie headers
|
||||
|
||||
// Modify headers (create new request)
|
||||
const modifiedRequest = new Request(request);
|
||||
modifiedRequest.headers.set("X-Custom", "value")
|
||||
modifiedRequest.headers.delete("X-Remove")
|
||||
```
|
||||
|
||||
### Cloudflare Properties (`request.cf`)
|
||||
Access Cloudflare-specific metadata about the request:
|
||||
|
||||
```javascript
|
||||
// Geolocation
|
||||
request.cf.city // "San Francisco"
|
||||
request.cf.continent // "NA"
|
||||
request.cf.country // "US"
|
||||
request.cf.region // "California" or "CA"
|
||||
request.cf.regionCode // "CA"
|
||||
request.cf.postalCode // "94102"
|
||||
request.cf.latitude // "37.7749"
|
||||
request.cf.longitude // "-122.4194"
|
||||
request.cf.timezone // "America/Los_Angeles"
|
||||
request.cf.metroCode // "807" (DMA code)
|
||||
|
||||
// Network
|
||||
request.cf.colo // "SFO" (airport code of datacenter)
|
||||
request.cf.asn // 13335 (ASN number)
|
||||
request.cf.asOrganization // "Cloudflare, Inc."
|
||||
|
||||
// Bot Management (if enabled)
|
||||
request.cf.botManagement.score // 1-99 (1=bot, 99=human)
|
||||
request.cf.botManagement.verified_bot // true/false
|
||||
request.cf.botManagement.static_resource // true/false
|
||||
|
||||
// TLS/HTTP version
|
||||
request.cf.tlsVersion // "TLSv1.3"
|
||||
request.cf.tlsCipher // "AEAD-AES128-GCM-SHA256"
|
||||
request.cf.httpProtocol // "HTTP/2"
|
||||
|
||||
// Request metadata
|
||||
request.cf.requestPriority // "weight=192;exclusive=0"
|
||||
```
|
||||
|
||||
**Use cases**: Geo-routing, bot detection, security decisions, analytics.
|
||||
|
||||
## Response Object
|
||||
|
||||
### Response Constructors
|
||||
```javascript
|
||||
// Plain text
|
||||
new Response("Hello", { status: 200 })
|
||||
|
||||
// JSON
|
||||
Response.json({ key: "value" }, { status: 200 })
|
||||
|
||||
// HTML
|
||||
new Response("<h1>Hi</h1>", {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "text/html" }
|
||||
})
|
||||
|
||||
// Redirect
|
||||
Response.redirect("https://example.com", 301) // or 302
|
||||
|
||||
// Stream (pass through)
|
||||
new Response(response.body, response)
|
||||
```
|
||||
|
||||
### Response Headers
|
||||
```javascript
|
||||
// Create modified response
|
||||
const newResponse = new Response(response.body, response);
|
||||
|
||||
// Set/modify headers
|
||||
newResponse.headers.set("X-Custom", "value")
|
||||
newResponse.headers.append("Set-Cookie", "session=abc; Path=/")
|
||||
newResponse.headers.delete("Server")
|
||||
|
||||
// Common headers
|
||||
newResponse.headers.set("Cache-Control", "public, max-age=3600")
|
||||
newResponse.headers.set("Content-Type", "application/json")
|
||||
```
|
||||
|
||||
### Response Properties
|
||||
```javascript
|
||||
response.status // 200, 404, 500, etc.
|
||||
response.statusText // "OK", "Not Found", etc.
|
||||
response.headers // Headers object
|
||||
response.body // ReadableStream
|
||||
response.ok // true if status 200-299
|
||||
response.redirected // true if redirected
|
||||
```
|
||||
|
||||
## REST API Operations
|
||||
|
||||
### List Snippets
|
||||
```bash
|
||||
GET /zones/{zone_id}/snippets
|
||||
```
|
||||
|
||||
### Get Snippet
|
||||
```bash
|
||||
GET /zones/{zone_id}/snippets/{snippet_name}
|
||||
```
|
||||
|
||||
### Create/Update Snippet
|
||||
```bash
|
||||
PUT /zones/{zone_id}/snippets/{snippet_name}
|
||||
Content-Type: multipart/form-data
|
||||
|
||||
files=@snippet.js
|
||||
metadata={"main_module":"snippet.js"}
|
||||
```
|
||||
|
||||
### Delete Snippet
|
||||
```bash
|
||||
DELETE /zones/{zone_id}/snippets/{snippet_name}
|
||||
```
|
||||
|
||||
### List Snippet Rules
|
||||
```bash
|
||||
GET /zones/{zone_id}/rulesets/phases/http_request_snippets/entrypoint
|
||||
```
|
||||
|
||||
### Update Snippet Rules
|
||||
```bash
|
||||
PUT /zones/{zone_id}/snippets/snippet_rules
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"rules": [{
|
||||
"description": "Apply snippet",
|
||||
"enabled": true,
|
||||
"expression": "http.host eq \"example.com\"",
|
||||
"snippet_name": "my_snippet"
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## Available APIs in Snippets
|
||||
|
||||
### ✅ Supported
|
||||
- `fetch()` - HTTP requests (2-5 subrequests per plan)
|
||||
- `Request` / `Response` - Standard Web APIs
|
||||
- `URL` / `URLSearchParams` - URL manipulation
|
||||
- `Headers` - Header manipulation
|
||||
- `TextEncoder` / `TextDecoder` - Text encoding
|
||||
- `crypto.subtle` - Web Crypto API (hashing, signing)
|
||||
- `crypto.randomUUID()` - UUID generation
|
||||
|
||||
### ❌ Not Supported in Snippets
|
||||
- `caches` API - Not available (use Workers)
|
||||
- `KV`, `D1`, `R2` - Storage APIs (use Workers)
|
||||
- `Durable Objects` - Stateful objects (use Workers)
|
||||
- `WebSocket` - WebSocket upgrades (use Workers)
|
||||
- `HTMLRewriter` - HTML parsing (use Workers)
|
||||
- `import` statements - No module imports
|
||||
- `addEventListener` - Use `export default { async fetch() {}` pattern
|
||||
|
||||
## Snippet Structure
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
// Your logic here
|
||||
const response = await fetch(request);
|
||||
return response; // or modified response
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,227 @@
|
||||
# Snippets Configuration Guide
|
||||
|
||||
## Configuration Methods
|
||||
|
||||
### 1. Dashboard (GUI)
|
||||
**Best for**: Quick tests, single snippets, visual rule building
|
||||
|
||||
```
|
||||
1. Go to zone → Rules → Snippets
|
||||
2. Click "Create Snippet" or select template
|
||||
3. Enter snippet name (a-z, 0-9, _ only, cannot change later)
|
||||
4. Write JavaScript code (32KB max)
|
||||
5. Configure snippet rule:
|
||||
- Expression Builder (visual) or Expression Editor (text)
|
||||
- Use Ruleset Engine filter expressions
|
||||
6. Test with Preview/HTTP tabs
|
||||
7. Deploy or Save as Draft
|
||||
```
|
||||
|
||||
### 2. REST API
|
||||
**Best for**: CI/CD, automation, programmatic management
|
||||
|
||||
```bash
|
||||
# Create/update snippet
|
||||
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/snippets/$SNIPPET_NAME" \
|
||||
--request PUT \
|
||||
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
||||
--form "files=@example.js" \
|
||||
--form "metadata={\"main_module\": \"example.js\"}"
|
||||
|
||||
# Create snippet rule
|
||||
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/snippets/snippet_rules" \
|
||||
--request PUT \
|
||||
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data '{
|
||||
"rules": [
|
||||
{
|
||||
"description": "Trigger snippet on /api paths",
|
||||
"enabled": true,
|
||||
"expression": "starts_with(http.request.uri.path, \"/api/\")",
|
||||
"snippet_name": "api_snippet"
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
# List snippets
|
||||
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/snippets" \
|
||||
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
|
||||
|
||||
# Delete snippet
|
||||
curl "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/snippets/$SNIPPET_NAME" \
|
||||
--request DELETE \
|
||||
--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
|
||||
```
|
||||
|
||||
### 3. Terraform
|
||||
**Best for**: Infrastructure-as-code, multi-zone deployments
|
||||
|
||||
```hcl
|
||||
# Configure Terraform provider
|
||||
terraform {
|
||||
required_providers {
|
||||
cloudflare = {
|
||||
source = "cloudflare/cloudflare"
|
||||
version = "~> 4.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "cloudflare" {
|
||||
api_token = var.cloudflare_api_token
|
||||
}
|
||||
|
||||
# Create snippet
|
||||
resource "cloudflare_snippet" "security_headers" {
|
||||
zone_id = var.zone_id
|
||||
name = "security_headers"
|
||||
|
||||
main_module = "security_headers.js"
|
||||
files {
|
||||
name = "security_headers.js"
|
||||
content = file("${path.module}/snippets/security_headers.js")
|
||||
}
|
||||
}
|
||||
|
||||
# Create snippet rule
|
||||
resource "cloudflare_snippet_rules" "security_rules" {
|
||||
zone_id = var.zone_id
|
||||
|
||||
rules {
|
||||
description = "Apply security headers to all requests"
|
||||
enabled = true
|
||||
expression = "true"
|
||||
snippet_name = cloudflare_snippet.security_headers.name
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Pulumi
|
||||
**Best for**: Multi-cloud IaC, TypeScript/Python/Go workflows
|
||||
|
||||
```typescript
|
||||
import * as cloudflare from "@pulumi/cloudflare";
|
||||
import * as fs from "fs";
|
||||
|
||||
// Create snippet
|
||||
const securitySnippet = new cloudflare.Snippet("security-headers", {
|
||||
zoneId: zoneId,
|
||||
name: "security_headers",
|
||||
mainModule: "security_headers.js",
|
||||
files: [{
|
||||
name: "security_headers.js",
|
||||
content: fs.readFileSync("./snippets/security_headers.js", "utf8"),
|
||||
}],
|
||||
});
|
||||
|
||||
// Create snippet rule
|
||||
const snippetRule = new cloudflare.SnippetRules("security-rules", {
|
||||
zoneId: zoneId,
|
||||
rules: [{
|
||||
description: "Apply security headers",
|
||||
enabled: true,
|
||||
expression: "true",
|
||||
snippetName: securitySnippet.name,
|
||||
}],
|
||||
});
|
||||
```
|
||||
|
||||
## Filter Expressions
|
||||
|
||||
Snippets use Cloudflare's Ruleset Engine expression language to determine when to execute.
|
||||
|
||||
### Common Expression Patterns
|
||||
|
||||
```javascript
|
||||
// Host matching
|
||||
http.host eq "example.com"
|
||||
http.host in {"example.com" "www.example.com"}
|
||||
http.host contains "example"
|
||||
|
||||
// Path matching
|
||||
http.request.uri.path eq "/api/users"
|
||||
starts_with(http.request.uri.path, "/api/")
|
||||
ends_with(http.request.uri.path, ".json")
|
||||
matches(http.request.uri.path, "^/api/v[0-9]+/")
|
||||
|
||||
// Query parameters
|
||||
http.request.uri.query contains "debug=true"
|
||||
|
||||
// Headers
|
||||
http.headers["user-agent"] contains "Mobile"
|
||||
http.headers["accept-language"] eq "en-US"
|
||||
|
||||
// Cookies
|
||||
http.cookie contains "session="
|
||||
|
||||
// Geolocation
|
||||
ip.geoip.country eq "US"
|
||||
ip.geoip.continent eq "EU"
|
||||
|
||||
// Bot detection (requires Bot Management)
|
||||
cf.bot_management.score lt 30
|
||||
|
||||
// Method
|
||||
http.request.method eq "POST"
|
||||
http.request.method in {"POST" "PUT" "PATCH"}
|
||||
|
||||
// Combine with logical operators
|
||||
http.host eq "example.com" and starts_with(http.request.uri.path, "/api/")
|
||||
ip.geoip.country eq "US" or ip.geoip.country eq "CA"
|
||||
not http.headers["user-agent"] contains "bot"
|
||||
```
|
||||
|
||||
### Expression Functions
|
||||
|
||||
| Function | Example | Description |
|
||||
|----------|---------|-------------|
|
||||
| `starts_with()` | `starts_with(http.request.uri.path, "/api/")` | Check prefix |
|
||||
| `ends_with()` | `ends_with(http.request.uri.path, ".json")` | Check suffix |
|
||||
| `contains()` | `contains(http.headers["user-agent"], "Mobile")` | Check substring |
|
||||
| `matches()` | `matches(http.request.uri.path, "^/api/")` | Regex match |
|
||||
| `lower()` | `lower(http.host) eq "example.com"` | Convert to lowercase |
|
||||
| `upper()` | `upper(http.headers["x-api-key"])` | Convert to uppercase |
|
||||
| `len()` | `len(http.request.uri.path) gt 100` | String length |
|
||||
|
||||
## Deployment Workflow
|
||||
|
||||
### Development
|
||||
1. Write snippet code locally
|
||||
2. Test syntax with `node snippet.js` or TypeScript compiler
|
||||
3. Deploy to Dashboard or use API with `Save as Draft`
|
||||
4. Test with Preview/HTTP tabs in Dashboard
|
||||
5. Enable rule when ready
|
||||
|
||||
### Production
|
||||
1. Store snippet code in version control
|
||||
2. Use Terraform/Pulumi for reproducible deployments
|
||||
3. Deploy to staging zone first
|
||||
4. Test with real traffic (use low-traffic subdomain)
|
||||
5. Apply to production zone
|
||||
6. Monitor with Analytics/Logpush
|
||||
|
||||
## Limits & Requirements
|
||||
|
||||
| Resource | Limit | Notes |
|
||||
|----------|-------|-------|
|
||||
| Snippet size | 32 KB | Per snippet, compressed |
|
||||
| Snippet name | 64 chars | `a-z`, `0-9`, `_` only, immutable |
|
||||
| Snippets per zone | 20 | Soft limit, contact support for more |
|
||||
| Rules per zone | 20 | One rule per snippet typical |
|
||||
| Expression length | 4096 chars | Per rule expression |
|
||||
|
||||
## Authentication
|
||||
|
||||
### API Token (Recommended)
|
||||
```bash
|
||||
# Create token at: https://dash.cloudflare.com/profile/api-tokens
|
||||
# Required permissions: Zone.Snippets:Edit, Zone.Rules:Edit
|
||||
export CLOUDFLARE_API_TOKEN="your_token_here"
|
||||
```
|
||||
|
||||
### API Key (Legacy)
|
||||
```bash
|
||||
export CLOUDFLARE_EMAIL="your@email.com"
|
||||
export CLOUDFLARE_API_KEY="your_global_api_key"
|
||||
```
|
||||
@@ -0,0 +1,86 @@
|
||||
# Gotchas & Best Practices
|
||||
|
||||
## Common Errors
|
||||
|
||||
### 1000: "Snippet execution failed"
|
||||
Runtime error or syntax error. Wrap code in try/catch:
|
||||
```javascript
|
||||
try { return await fetch(request); }
|
||||
catch (error) { return new Response(`Error: ${error.message}`, { status: 500 }); }
|
||||
```
|
||||
|
||||
### 1100: "Exceeded execution limit"
|
||||
Code takes >5ms CPU. Simplify logic or move to Workers.
|
||||
|
||||
### 1201: "Multiple origin fetches"
|
||||
Call `fetch(request)` exactly once:
|
||||
```javascript
|
||||
// ❌ Multiple origin fetches
|
||||
const r1 = await fetch(request); const r2 = await fetch(request);
|
||||
// ✅ Single fetch, reuse response
|
||||
const response = await fetch(request);
|
||||
```
|
||||
|
||||
### 1202: "Subrequest limit exceeded"
|
||||
Pro: 2 subrequests, Business/Enterprise: 5. Reduce fetch calls.
|
||||
|
||||
### "Cannot set property on immutable object"
|
||||
Clone before modifying:
|
||||
```javascript
|
||||
const modifiedRequest = new Request(request);
|
||||
modifiedRequest.headers.set("X-Custom", "value");
|
||||
```
|
||||
|
||||
### "caches is not defined"
|
||||
Cache API NOT available in Snippets. Use Workers.
|
||||
|
||||
### "Module not found"
|
||||
Snippets don't support `import`. Use inline code or Workers.
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Performance
|
||||
- Keep code <10KB (32KB limit)
|
||||
- Optimize for 5ms CPU
|
||||
- Clone only when modifying
|
||||
- Minimize subrequests
|
||||
|
||||
### Security
|
||||
- Validate all inputs
|
||||
- Use Web Crypto API for hashing
|
||||
- Sanitize headers before origin
|
||||
- Don't log secrets
|
||||
|
||||
### Debugging
|
||||
```javascript
|
||||
newResponse.headers.set("X-Debug-Country", request.cf.country);
|
||||
```
|
||||
```bash
|
||||
curl -H "X-Test: true" https://example.com -v
|
||||
```
|
||||
|
||||
## Available APIs
|
||||
|
||||
**✅ Available:** `fetch()`, `Request`, `Response`, `Headers`, `URL`, `crypto.subtle`, `crypto.randomUUID()`, `atob()`/`btoa()`, `JSON`
|
||||
|
||||
**❌ NOT Available:** `caches`, `KV`, `D1`, `R2`, `Durable Objects`, `WebSocket`, `HTMLRewriter`, `import`, Node.js APIs
|
||||
|
||||
## Limits
|
||||
|
||||
| Resource | Limit |
|
||||
|----------|-------|
|
||||
| Snippet size | 32KB |
|
||||
| Execution time | 5ms CPU |
|
||||
| Subrequests (Pro/Biz) | 2/5 |
|
||||
| Snippets/zone | 20 |
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
| Operation | Time |
|
||||
|-----------|------|
|
||||
| Header set | <0.1ms |
|
||||
| URL parsing | <0.2ms |
|
||||
| fetch() | 1-3ms |
|
||||
| SHA-256 | 0.5-1ms |
|
||||
|
||||
**Migrate to Workers when:** >5ms needed, >5 subrequests, need storage (KV/D1/R2), need npm packages, >32KB code
|
||||
135
.agents/skills/cloudflare-deploy/references/snippets/patterns.md
Normal file
135
.agents/skills/cloudflare-deploy/references/snippets/patterns.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Snippets Patterns
|
||||
|
||||
## Security Headers
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
const response = await fetch(request);
|
||||
const newResponse = new Response(response.body, response);
|
||||
newResponse.headers.set("X-Frame-Options", "DENY");
|
||||
newResponse.headers.set("X-Content-Type-Options", "nosniff");
|
||||
newResponse.headers.delete("X-Powered-By");
|
||||
return newResponse;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Rule:** `true` (all requests)
|
||||
|
||||
## Geo-Based Routing
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
const country = request.cf.country;
|
||||
if (["GB", "DE", "FR"].includes(country)) {
|
||||
const url = new URL(request.url);
|
||||
url.hostname = url.hostname.replace(".com", ".eu");
|
||||
return Response.redirect(url.toString(), 302);
|
||||
}
|
||||
return fetch(request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## A/B Testing
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
const cookies = request.headers.get("Cookie") || "";
|
||||
let variant = cookies.match(/ab_test=([AB])/)?.[1] || (Math.random() < 0.5 ? "A" : "B");
|
||||
|
||||
const req = new Request(request);
|
||||
req.headers.set("X-Variant", variant);
|
||||
const response = await fetch(req);
|
||||
|
||||
if (!cookies.includes("ab_test=")) {
|
||||
const newResponse = new Response(response.body, response);
|
||||
newResponse.headers.append("Set-Cookie", `ab_test=${variant}; Path=/; Secure`);
|
||||
return newResponse;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Bot Detection
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
const botScore = request.cf.botManagement?.score;
|
||||
if (botScore && botScore < 30) return new Response("Denied", { status: 403 });
|
||||
return fetch(request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Requires:** Bot Management plan
|
||||
|
||||
## API Auth Header Injection
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
if (new URL(request.url).pathname.startsWith("/api/")) {
|
||||
const req = new Request(request);
|
||||
req.headers.set("X-Internal-Auth", "secret_token");
|
||||
req.headers.delete("Authorization");
|
||||
return fetch(req);
|
||||
}
|
||||
return fetch(request);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CORS Headers
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
if (request.method === "OPTIONS") {
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
|
||||
"Access-Control-Allow-Headers": "Content-Type, Authorization"
|
||||
}
|
||||
});
|
||||
}
|
||||
const response = await fetch(request);
|
||||
const newResponse = new Response(response.body, response);
|
||||
newResponse.headers.set("Access-Control-Allow-Origin", "*");
|
||||
return newResponse;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Maintenance Mode
|
||||
|
||||
```javascript
|
||||
export default {
|
||||
async fetch(request) {
|
||||
if (request.headers.get("X-Bypass-Token") === "admin") return fetch(request);
|
||||
return new Response("<h1>Maintenance</h1>", {
|
||||
status: 503,
|
||||
headers: { "Content-Type": "text/html", "Retry-After": "3600" }
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Pattern Selection
|
||||
|
||||
| Pattern | Complexity | Use Case |
|
||||
|---------|-----------|----------|
|
||||
| Security Headers | Low | All sites |
|
||||
| Geo-Routing | Low | Regional content |
|
||||
| A/B Testing | Medium | Experiments |
|
||||
| Bot Detection | Medium | Requires Bot Management |
|
||||
| API Auth | Low | Backend protection |
|
||||
| CORS | Low | API endpoints |
|
||||
| Maintenance | Low | Deployments |
|
||||
Reference in New Issue
Block a user