mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 18:11:27 -07:00
update skills
This commit is contained in:
199
.agents/skills/cloudflare-deploy/references/static-assets/api.md
Normal file
199
.agents/skills/cloudflare-deploy/references/static-assets/api.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# API Reference
|
||||
|
||||
## ASSETS Binding
|
||||
|
||||
The `ASSETS` binding provides access to static assets via the `Fetcher` interface.
|
||||
|
||||
### Type Definition
|
||||
|
||||
```typescript
|
||||
interface Env {
|
||||
ASSETS: Fetcher;
|
||||
}
|
||||
|
||||
interface Fetcher {
|
||||
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
||||
}
|
||||
```
|
||||
|
||||
### Method Signatures
|
||||
|
||||
```typescript
|
||||
// 1. Forward entire request
|
||||
await env.ASSETS.fetch(request);
|
||||
|
||||
// 2. String path (hostname ignored, only path matters)
|
||||
await env.ASSETS.fetch("https://any-host/path/to/asset.png");
|
||||
|
||||
// 3. URL object
|
||||
await env.ASSETS.fetch(new URL("/index.html", request.url));
|
||||
|
||||
// 4. Constructed Request object
|
||||
await env.ASSETS.fetch(new Request(new URL("/logo.png", request.url), {
|
||||
method: "GET",
|
||||
headers: request.headers
|
||||
}));
|
||||
```
|
||||
|
||||
**Key behaviors:**
|
||||
|
||||
- Host/origin is ignored for string/URL inputs (only path is used)
|
||||
- Method must be GET (others return 405)
|
||||
- Request headers pass through (affects response)
|
||||
- Returns standard `Response` object
|
||||
|
||||
## Request Handling
|
||||
|
||||
### Path Resolution
|
||||
|
||||
```typescript
|
||||
// All resolve to same asset:
|
||||
env.ASSETS.fetch("https://example.com/logo.png")
|
||||
env.ASSETS.fetch("https://ignored.host/logo.png")
|
||||
env.ASSETS.fetch("/logo.png")
|
||||
```
|
||||
|
||||
Assets are resolved relative to configured `assets.directory`.
|
||||
|
||||
### Headers
|
||||
|
||||
Request headers that affect response:
|
||||
|
||||
| Header | Effect |
|
||||
|--------|--------|
|
||||
| `Accept-Encoding` | Controls compression (gzip, brotli) |
|
||||
| `Range` | Enables partial content (206 responses) |
|
||||
| `If-None-Match` | Conditional request via ETag |
|
||||
| `If-Modified-Since` | Conditional request via modification date |
|
||||
|
||||
Custom headers pass through but don't affect asset serving.
|
||||
|
||||
### Method Support
|
||||
|
||||
| Method | Supported | Response |
|
||||
|--------|-----------|----------|
|
||||
| `GET` | ✅ Yes | Asset content |
|
||||
| `HEAD` | ✅ Yes | Headers only, no body |
|
||||
| `POST`, `PUT`, etc. | ❌ No | 405 Method Not Allowed |
|
||||
|
||||
## Response Behavior
|
||||
|
||||
### Content-Type Inference
|
||||
|
||||
Automatically set based on file extension:
|
||||
|
||||
| Extension | Content-Type |
|
||||
|-----------|--------------|
|
||||
| `.html` | `text/html; charset=utf-8` |
|
||||
| `.css` | `text/css` |
|
||||
| `.js` | `application/javascript` |
|
||||
| `.json` | `application/json` |
|
||||
| `.png` | `image/png` |
|
||||
| `.jpg`, `.jpeg` | `image/jpeg` |
|
||||
| `.svg` | `image/svg+xml` |
|
||||
| `.woff2` | `font/woff2` |
|
||||
|
||||
### Default Headers
|
||||
|
||||
Responses include:
|
||||
|
||||
```
|
||||
Content-Type: <inferred>
|
||||
ETag: "<hash>"
|
||||
Cache-Control: public, max-age=3600
|
||||
Content-Encoding: br (if supported and beneficial)
|
||||
```
|
||||
|
||||
**Cache-Control defaults:**
|
||||
|
||||
- 1 hour (`max-age=3600`) for most assets
|
||||
- Override via Worker response transformation (see patterns.md:27-35)
|
||||
|
||||
### Compression
|
||||
|
||||
Automatic compression based on `Accept-Encoding`:
|
||||
|
||||
- **Brotli** (`br`): Preferred, best compression
|
||||
- **Gzip** (`gzip`): Fallback
|
||||
- **None**: If client doesn't support or asset too small
|
||||
|
||||
### ETag Generation
|
||||
|
||||
ETags are content-based hashes:
|
||||
|
||||
```
|
||||
ETag: "a3b2c1d4e5f6..."
|
||||
```
|
||||
|
||||
Used for conditional requests (`If-None-Match`). Returns `304 Not Modified` if match.
|
||||
|
||||
## Error Responses
|
||||
|
||||
| Status | Condition | Behavior |
|
||||
|--------|-----------|----------|
|
||||
| `404` | Asset not found | Body depends on `not_found_handling` config |
|
||||
| `405` | Non-GET/HEAD method | `{ "error": "Method not allowed" }` |
|
||||
| `416` | Invalid Range header | Range not satisfiable |
|
||||
|
||||
### 404 Handling
|
||||
|
||||
Depends on configuration (see configuration.md:45-52):
|
||||
|
||||
```typescript
|
||||
// not_found_handling: "single-page-application"
|
||||
// Returns /index.html with 200 status
|
||||
|
||||
// not_found_handling: "404-page"
|
||||
// Returns /404.html if exists, else 404 response
|
||||
|
||||
// not_found_handling: "none"
|
||||
// Returns 404 response
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Modifying Responses
|
||||
|
||||
```typescript
|
||||
const response = await env.ASSETS.fetch(request);
|
||||
|
||||
// Clone and modify
|
||||
return new Response(response.body, {
|
||||
status: response.status,
|
||||
headers: {
|
||||
...Object.fromEntries(response.headers),
|
||||
'Cache-Control': 'public, max-age=31536000',
|
||||
'X-Custom': 'value'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
See patterns.md:27-35 for full example.
|
||||
|
||||
### Error Handling
|
||||
|
||||
```typescript
|
||||
const response = await env.ASSETS.fetch(request);
|
||||
|
||||
if (!response.ok) {
|
||||
// Asset not found or error
|
||||
return new Response('Custom error page', { status: 404 });
|
||||
}
|
||||
|
||||
return response;
|
||||
```
|
||||
|
||||
### Conditional Serving
|
||||
|
||||
```typescript
|
||||
const url = new URL(request.url);
|
||||
|
||||
// Serve different assets based on conditions
|
||||
if (url.pathname === '/') {
|
||||
return env.ASSETS.fetch('/index.html');
|
||||
}
|
||||
|
||||
return env.ASSETS.fetch(request);
|
||||
```
|
||||
|
||||
See patterns.md for complete patterns.
|
||||
Reference in New Issue
Block a user