{"id":13727224,"url":"https://github.com/cakedan/cf-worker-router","last_synced_at":"2025-05-07T22:30:55.672Z","repository":{"id":57196276,"uuid":"168290008","full_name":"cakedan/cf-worker-router","owner":"cakedan","description":"Cloudflare Worker Router","archived":false,"fork":false,"pushed_at":"2019-09-22T06:43:56.000Z","size":29,"stargazers_count":22,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-13T01:18:05.374Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cakedan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-30T06:17:30.000Z","updated_at":"2023-11-09T14:47:04.000Z","dependencies_parsed_at":"2022-09-16T12:21:07.272Z","dependency_job_id":null,"html_url":"https://github.com/cakedan/cf-worker-router","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cakedan%2Fcf-worker-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cakedan%2Fcf-worker-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cakedan%2Fcf-worker-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cakedan%2Fcf-worker-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cakedan","download_url":"https://codeload.github.com/cakedan/cf-worker-router/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252965255,"owners_count":21832852,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T01:03:44.876Z","updated_at":"2025-05-07T22:30:55.360Z","avatar_url":"https://github.com/cakedan.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Cloudflare Worker Router\neasier cloudflare request routing\n\n## Example Usage\n```js\nimport { ApiError, ApiRedirect, DomainRouter, FetchRouter } from 'cf-worker-router';\n\nconst router = new FetchRouter();\n\n// add the cloudflare event listener\naddEventListener('fetch', (event) =\u003e {\n  router.onFetch(event);\n});\n\n// after every response, modify it (like setting CORS headers)\n// is optional\nrouter.beforeResponse = (response, event) =\u003e {\n  // create a new Response instance, incase it's immutable like from a fetch request\n  response = new Response(response.body, response);\n  response.headers.set('access-control-allow-headers', 'Content-Type, X-Some-Header');\n  response.headers.set('access-control-allow-methods', '*');\n  response.headers.set('access-control-allow-origin', event.url.origin || '*');\n  return response;\n};\n\n\n// same as .route(url, 'GET', handler);\n// GET */users/1234\nrouter.route('/users/:userId', async (event) =\u003e {\n  // automatically converts anything not of Response type to ApiResponse\n  return event.parameters;\n});\n\n// same as .route(url, ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], handler)\n// ANY-METHOD */proxy/:url\nrouter.route('/proxy/:url', '*', async (event) =\u003e {\n  if (event.request.headers.get('secret-token') !== 'test') {\n    return new ApiError({status: 403});\n  }\n  // remove our ip from headers\n  event.request.headers.delete('cf-connecting-ip');\n  event.request.headers.delete('x-real-ip');\n  return await fetch(event.parameters.url, event.request);\n});\n\n// GET redirect.example.com/:url\nrouter.route('redirect.example.com/:url', async (event) =\u003e {\n  return new ApiRedirect(event.parameters.url);\n});\n\n// GET example.com/string-test/anystringhere\n// GET example.com/string-test/anystringhere/andanythingwithslashes\nrouter.route('example.com/string-test/:string...', async (event) =\u003e {\n  return event.parameters;\n});\n\n// GET example.club/pass\n// passes it onto original destination, doesn't call `event.respondWith()`\nrouter.route('example.com/pass', {pass: true});\n\n\nconst subDomain = new DomainRouter(':username.example.com');\nrouter.addRouter(subDomain);\n\n// GET some-username.example.com/files/1234\nsubDomain.get('/files/:fileId', async (event) =\u003e {\n  // {username, fileId} are the parameters\n  return event.parameters;\n});\n\n```\n\n## Example Usage w/ Minified Version\n```js\n// Copy and Paste ./min/router.min.js at the top of the file\n// !function(e){...\n\n// We put our library in self.CFWorkerRouter\nconst { ApiError, ApiRedirect, DomainRouter, FetchRouter } = CFWorkerRouter;\n\nconst router = new FetchRouter();\n\n// add the cloudflare event listener\naddEventListener('fetch', (event) =\u003e {\n  router.onFetch(event);\n});\n\n// after every response, modify it (like setting CORS headers)\n// is optional\nrouter.beforeResponse = (response, event) =\u003e {\n  // create a new Response instance, incase it's immutable like from a fetch request\n  response = new Response(response.body, response);\n  response.headers.set('access-control-allow-headers', 'Content-Type, X-Some-Header');\n  response.headers.set('access-control-allow-methods', '*');\n  response.headers.set('access-control-allow-origin', event.url.origin || '*');\n  return response;\n};\n\n\n// same as .route(url, 'GET', handler);\n// GET */users/1234\nrouter.route('/users/:userId', async (event) =\u003e {\n  // automatically converts anything not of Response type to ApiResponse\n  return event.parameters;\n});\n\n// same as .route(url, ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'], handler)\n// ANY-METHOD */proxy/:url\nrouter.route('/proxy/:url', '*', async (event) =\u003e {\n  if (event.request.headers.get('secret-token') !== 'test') {\n    return new ApiError({status: 403});\n  }\n  // remove our ip from headers\n  event.request.headers.delete('cf-connecting-ip');\n  event.request.headers.delete('x-real-ip');\n  return await fetch(event.parameters.url, event.request);\n});\n\n// GET redirect.example.com/:url\nrouter.route('redirect.example.com/:url', async (event) =\u003e {\n  return new ApiRedirect(event.parameters.url);\n});\n\n// GET example.com/string-test/anystringhere\n// GET example.com/string-test/anystringhere/andanythingwithslashes\nrouter.route('example.com/string-test/:string...', async (event) =\u003e {\n  return event.parameters;\n});\n\n// GET example.club/pass\n// passes it onto original destination, doesn't call `event.respondWith()`\nrouter.route('example.com/pass', {pass: true});\n\n\nconst subDomain = new DomainRouter(':username.example.com');\nrouter.addRouter(subDomain);\n\n// GET some-username.example.com/files/1234\nsubDomain.get('/files/:fileId', async (event) =\u003e {\n  // {username, fileId} are the parameters\n  return event.parameters;\n});\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcakedan%2Fcf-worker-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcakedan%2Fcf-worker-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcakedan%2Fcf-worker-router/lists"}