From 168093e034e0213faeac3198356b4fc2cc8ac48a Mon Sep 17 00:00:00 2001 From: uh_wot Date: Sun, 24 Jan 2021 15:41:29 +0100 Subject: [PATCH] initial commit --- .gitignore | 4 ++ .prettierrc | 6 +++ README.md | 25 +++++++++++ index.js | 30 +++++++++++++ package.json | 18 ++++++++ router.js | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ wrangler.toml | 6 +++ 7 files changed, 210 insertions(+) create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 README.md create mode 100644 index.js create mode 100644 package.json create mode 100644 router.js create mode 100644 wrangler.toml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..635bd4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +worker/ +.cargo-ok +package-lock.json diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ef58ff9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 4, + "semi": false, + "singleQuote": true +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..cfb35b1 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +## Router + +Selects the logic to respond to requests based on the `request` method and URL. Can be used with REST APIs or apps that require basic routing logic. + +[`index.js`](https://github.com/cloudflare/worker-template-router/blob/master/index.js) is the content of the Workers script. + +#### Wrangler + +You can use [wrangler](https://github.com/cloudflare/wrangler) to generate a new Cloudflare Workers project based on this template by running the following command from your terminal: + +``` +wrangler generate myapp https://github.com/cloudflare/worker-template-router +``` + +Before publishing your code you need to edit `wrangler.toml` file and add your Cloudflare `account_id` - more information about publishing your code can be found [in the documentation](https://workers.cloudflare.com/docs/quickstart/configuring-and-publishing/). + +Once you are ready, you can publish your code by running the following command: + +``` +wrangler publish +``` + +#### Serverless + +To deploy using serverless add a [`serverless.yml`](https://serverless.com/framework/docs/providers/cloudflare/) file. diff --git a/index.js b/index.js new file mode 100644 index 0000000..2cdca8e --- /dev/null +++ b/index.js @@ -0,0 +1,30 @@ +const Router = require('./router') + +/** + * Example of how router can be used in an application + * */ +addEventListener('fetch', event => { + event.respondWith(handleRequest(event.request)) +}) + +function handler(request) { + const init = { + headers: { 'content-type': 'application/json' }, + } + const body = JSON.stringify({ some: 'json' }) + return new Response(body, init) +} + +async function handleRequest(request) { + const r = new Router() + // Replace with the appropriate paths and handlers + r.get('.*/bar', () => new Response('responding for /bar')) + r.get('.*/foo', request => handler(request)) + r.post('.*/foo.*', request => handler(request)) + r.get('/demos/router/foo', request => fetch(request)) // return the response from the origin + + r.get('/', () => new Response('Hello worker!')) // return a default message for the root route + + const resp = await r.route(request) + return resp +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..316b472 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "dzserver", + "version": "1.0.0", + "description": "package for creating workers templates", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "format": "prettier --write '**/*.{js,css,json,md}'" + }, + "author": "uh_wot ", + "license": "ISC", + "devDependencies": { + "prettier": "^1.17.0" + }, + "dependencies": { + "serverless-cloudflare-workers": "^1.2.0" + } +} diff --git a/router.js b/router.js new file mode 100644 index 0000000..6e1fb94 --- /dev/null +++ b/router.js @@ -0,0 +1,121 @@ +/** + * Helper functions that when passed a request will return a + * boolean indicating if the request uses that HTTP method, + * header, host or referrer. + */ +const Method = method => req => + req.method.toLowerCase() === method.toLowerCase() +const Connect = Method('connect') +const Delete = Method('delete') +const Get = Method('get') +const Head = Method('head') +const Options = Method('options') +const Patch = Method('patch') +const Post = Method('post') +const Put = Method('put') +const Trace = Method('trace') + +const Header = (header, val) => req => req.headers.get(header) === val +const Host = host => Header('host', host.toLowerCase()) +const Referrer = host => Header('referrer', host.toLowerCase()) + +const Path = regExp => req => { + const url = new URL(req.url) + const path = url.pathname + const match = path.match(regExp) || [] + return match[0] === path +} + +/** + * The Router handles determines which handler is matched given the + * conditions present for each request. + */ +class Router { + constructor() { + this.routes = [] + } + + handle(conditions, handler) { + this.routes.push({ + conditions, + handler, + }) + return this + } + + connect(url, handler) { + return this.handle([Connect, Path(url)], handler) + } + + delete(url, handler) { + return this.handle([Delete, Path(url)], handler) + } + + get(url, handler) { + return this.handle([Get, Path(url)], handler) + } + + head(url, handler) { + return this.handle([Head, Path(url)], handler) + } + + options(url, handler) { + return this.handle([Options, Path(url)], handler) + } + + patch(url, handler) { + return this.handle([Patch, Path(url)], handler) + } + + post(url, handler) { + return this.handle([Post, Path(url)], handler) + } + + put(url, handler) { + return this.handle([Put, Path(url)], handler) + } + + trace(url, handler) { + return this.handle([Trace, Path(url)], handler) + } + + all(handler) { + return this.handle([], handler) + } + + route(req) { + const route = this.resolve(req) + + if (route) { + return route.handler(req) + } + + return new Response('resource not found', { + status: 404, + statusText: 'not found', + headers: { + 'content-type': 'text/plain', + }, + }) + } + + /** + * resolve returns the matching route for a request that returns + * true for all conditions (if any). + */ + resolve(req) { + return this.routes.find(r => { + if (!r.conditions || (Array.isArray(r) && !r.conditions.length)) { + return true + } + + if (typeof r.conditions === 'function') { + return r.conditions(req) + } + + return r.conditions.every(c => c(req)) + }) + } +} + +module.exports = Router diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..0bc6a52 --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,6 @@ +name = "dzserver" +type = "webpack" +account_id = "03479b0523a52b140e0dabac40cb0fc8" +workers_dev = true +route = "" +zone_id = ""