Skip to content

Cloudflare

Alex Bruno CΓ‘ceres edited this page Jul 24, 2023 · 7 revisions

Utilities to help web development for Cloudflare hosting.

workers

@jsweb/utils/cloudflare/workers

Helper module to simplify development for Cloudflare Workers, and for Cloudflare Pages Functions in "Advanced Mode", which is nothing else than a Worker (https://developers.cloudflare.com/pages/platform/functions/advanced-mode/).

SimpleRouter

A class to easily implement a router for your cloud functions endpoints.

It is a simple but powerful class, supporting CORS, express-like dynamic params for your URLs, and any other ways to properly handle requests with native JS objects only like Request, URL, and Map.

The whole source code is just around 170 TypeScript lines, including all the interface and type declarations, with no dependencies except some @cloudflare/workers-types.

Enjoy the power of a lightweight, concise, objective, clean, and intuitive routing API for your Cloudflare Workers!

// Worker code

import { SimpleRouter } from '@jsweb/utils/cloudflare/workers'
import LoremIpsum from './lorem/ipsum'
import DolorSit from './dolor/sit'
import {
  AmetConsecturGet,
  AmetConsecturPost,
  AmetConsecturPut,
  AmetConsecturDelete
} from './amet/consectur'

const api = new SimpleRouter('/api/') // Instance with a base URL pathname

// Each route can accept one or more methods
api.set('lorem/ispum', { GET: LoremIpsum })
api.set('dolor/sit', { POST: DolorSit })
api.set('amet/:consectur', {
  GET: AmetConsecturGet,
  POST: AmetConsecturPost,
  PUT: AmetConsecturPut,
  DELETE: AmetConsecturDelete,
})

export default api.handler()

// Request to any other URL paths will automatically fall back to
// the Cloudflare ASSETS server, serving your static files, for example.

Handful APIs inside your functions!

Ex.:

// Endpoint function code

import type { WorkerEnv, WorkerKV, WorkerFunction } from '@jsweb/utils/cloudflare/workers'

interface Env extends WorkerEnv {
  DATA: WorkerKV
}

const endpoint: WorkerFunction<Env> = async function({ req, url, params, env }) {
  // **req** is the Request object βœ…
  const { name, email, phone, message } = await req.json<any>()
  
  // **url** is a URL object instance for the request πŸ‘πŸΌ
  const key = url.searchParams.get('key')

  // **params** is a Map object containing key: value pairs
  // for your dynamic URL params, for example: '/api/users/:user' πŸš€
  const user = params.get('user')

  // **env** is the WorkerEnv object,
  // which extends the Cloudflare Env context object πŸ˜‰
  const data = await env.DATA.get('...')

  // Do your magic... πŸͺ„
  try {
    // ...
    return new Response('Ok')
  } catch (error) {
    // ...
    return new Response(error, { status: 500 })
  }
}

export default endpoint

CORS

Do you need CORS setup, ok there you go:

import { SimpleRouter } from '@jsweb/utils/cloudflare/workers'

// If you believe in a wonderful world...
const api = new SimpleRouter('/api/', { origins: ['*'] })

// Just for close friends? Ok!
// Authorized domains only, in addition to the host itself.
const api = new SimpleRouter('/api/', {
  origins: ['https://totally.reliable.com', 'https://my.friendbook.com']
})

// Nope, my APIs are private!
const api = new SimpleRouter('/api/')

Routers stack

It is also possible to attach more class instances with different base paths to your router. The .handler() method can receive other SimpleRouter instances as arguments to build a "routers stack", handling all of them at once.

import { SimpleRouter } from '@jsweb/utils/cloudflare/workers'
// ...

const api = new SimpleRouter('/api/')
// ...

const data = new SimpleRouter('/data/')
// ...

const mail = new SimpleRouter('/mail/')
// ...

export default api.handler(data, mail)

Proper HTTP responses

Cloudflare Pages Functions server has some issues around HTTP status responses when you are using the standalone function structure described in their documentation.

For example, if you send a POST request to a non-existent URL path, it responds with a 405 Method Not Allowed instead of a 404 Not Found. That is a totally wrong response to a non-existent URL. This issue was already reported to the dev support team through the community forum, but they think that the annoying wrong response is correct. (https://community.cloudflare.com/t/wrong-http-status-response-when-post-to-a-non-existent-function-url/443624)

But SimpleRouter is intelligent enough to handle proper HTTP responses for common request cases:

  • 404 Not Found: If any request is sent to a non-existent URL path under the router base path, for ANY HTTP METHOD
  • 405 Method Not Allowed: ONLY IF a request is sent to a VALID URL path under the router base path, but the endpoint DOES NOT ACCEPT THE INCOMING HTTP METHOD

If the request is ok, so it hits your target function, and you can handle proper responses according to your logic.

So, no issues around annoying responses and no wasting time by debugging errors that are not yours! πŸ˜‰

Clone this wiki locally