purge cache with DELETE method
This commit is contained in:
15
CLAUDE.md
15
CLAUDE.md
@@ -19,6 +19,8 @@ This is a Cloudflare Workers project called "url-cleaner" built with TypeScript.
|
|||||||
|
|
||||||
## API Usage
|
## API Usage
|
||||||
|
|
||||||
|
### Clean URL Endpoint
|
||||||
|
|
||||||
**Endpoint**: `GET /?url=<encoded-url>`
|
**Endpoint**: `GET /?url=<encoded-url>`
|
||||||
**Response**: Plain text containing the cleaned URL
|
**Response**: Plain text containing the cleaned URL
|
||||||
|
|
||||||
@@ -27,6 +29,16 @@ This is a Cloudflare Workers project called "url-cleaner" built with TypeScript.
|
|||||||
- `/?url=https://example.com?utm_source=test` → `https://example.com`
|
- `/?url=https://example.com?utm_source=test` → `https://example.com`
|
||||||
- `/?url=https://youtube.com/watch?v=abc&feature=share` → `https://youtube.com/watch?v=abc`
|
- `/?url=https://youtube.com/watch?v=abc&feature=share` → `https://youtube.com/watch?v=abc`
|
||||||
|
|
||||||
|
### Cache Purge Endpoint
|
||||||
|
|
||||||
|
**Endpoint**: `DELETE /?url=<encoded-url>`
|
||||||
|
**Response**: Plain text confirming cache deletion
|
||||||
|
|
||||||
|
**Examples**:
|
||||||
|
|
||||||
|
- `DELETE /?url=https://example.com?utm_source=test` → `Cache entry deleted` (200)
|
||||||
|
- `DELETE /?url=https://nonexistent.com` → `Cache entry not found` (404)
|
||||||
|
|
||||||
## Common Commands
|
## Common Commands
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
@@ -67,7 +79,8 @@ test/
|
|||||||
- **Fragment Cleaning**: Removes tracking from URL fragments/hash parameters (`#utm_campaign=test`)
|
- **Fragment Cleaning**: Removes tracking from URL fragments/hash parameters (`#utm_campaign=test`)
|
||||||
- **Raw Rules Support**: Handles complex regex-based cleaning for advanced tracking patterns
|
- **Raw Rules Support**: Handles complex regex-based cleaning for advanced tracking patterns
|
||||||
- **Loop Prevention**: Tracks visited URLs to prevent infinite redirect loops
|
- **Loop Prevention**: Tracks visited URLs to prevent infinite redirect loops
|
||||||
- **Response Caching**: 1-hour cache for improved performance
|
- **Response Caching**: 1-hour cache using Cloudflare Cache API for improved performance
|
||||||
|
- **Cache Management**: DELETE endpoint for manual cache purging
|
||||||
|
|
||||||
### Rule System
|
### Rule System
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
"deploy": "wrangler deploy",
|
"deploy": "wrangler deploy",
|
||||||
"dev": "wrangler dev",
|
"dev": "wrangler dev",
|
||||||
"start": "wrangler dev",
|
"start": "wrangler dev",
|
||||||
"test": "vitest",
|
"test": "vitest --run",
|
||||||
"cf-typegen": "wrangler types",
|
"cf-typegen": "wrangler types",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"format:check": "prettier --check ."
|
"format:check": "prettier --check ."
|
||||||
|
11
src/index.ts
11
src/index.ts
@@ -19,6 +19,17 @@ export default {
|
|||||||
const cache = caches.default;
|
const cache = caches.default;
|
||||||
const cacheKey = new Request(`${url.origin}/cache/${encodeURIComponent(targetUrl)}`);
|
const cacheKey = new Request(`${url.origin}/cache/${encodeURIComponent(targetUrl)}`);
|
||||||
|
|
||||||
|
if (request.method === "DELETE") {
|
||||||
|
const deleted = await cache.delete(cacheKey);
|
||||||
|
return new Response(deleted ? "Cache entry deleted" : "Cache entry not found", {
|
||||||
|
status: deleted ? 200 : 404,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "text/plain",
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let response = await cache.match(cacheKey);
|
let response = await cache.match(cacheKey);
|
||||||
if (response) {
|
if (response) {
|
||||||
return response;
|
return response;
|
||||||
|
@@ -157,4 +157,35 @@ describe("URL Cleaner worker", () => {
|
|||||||
expect(response.status).toBe(200); // Should return original URL, not error
|
expect(response.status).toBe(200); // Should return original URL, not error
|
||||||
expect(await response.text()).toBe("not-a-valid-url");
|
expect(await response.text()).toBe("not-a-valid-url");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("deletes cache entry on DELETE request", async () => {
|
||||||
|
// First, make a GET request to cache the response
|
||||||
|
const testUrl = "https://tiktok.com/video?_t=tracking&_r=more&u_code=123&normal=keep&other=stay";
|
||||||
|
const getResponse = await SELF.fetch(`https://example.com/?url=${encodeURIComponent(testUrl)}`);
|
||||||
|
expect(getResponse.status).toBe(200);
|
||||||
|
expect(await getResponse.text()).toBe("https://tiktok.com/video?normal=keep&other=stay");
|
||||||
|
|
||||||
|
// Then delete the cache entry
|
||||||
|
const deleteResponse = await SELF.fetch(`https://example.com/?url=${encodeURIComponent(testUrl)}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
expect(deleteResponse.status).toBe(200);
|
||||||
|
expect(await deleteResponse.text()).toBe("Cache entry deleted");
|
||||||
|
|
||||||
|
const subsequentDeleteResponse = await SELF.fetch(`https://example.com/?url=${encodeURIComponent(testUrl)}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
expect(subsequentDeleteResponse.status).toBe(404);
|
||||||
|
expect(await subsequentDeleteResponse.text()).toBe("Cache entry not found");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns 404 when deleting non-existent cache entry", async () => {
|
||||||
|
const testUrl = "https://nonexistent.com?param=value";
|
||||||
|
|
||||||
|
const deleteResponse = await SELF.fetch(`https://example.com/?url=${encodeURIComponent(testUrl)}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
});
|
||||||
|
expect(deleteResponse.status).toBe(404);
|
||||||
|
expect(await deleteResponse.text()).toBe("Cache entry not found");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user