cf-workers-utils v1.1.0
cf-workers-utils
Overview
This package provides opinionated utility functions for creating responses, authentication and binary data manipulation, designed to be used with Cloudflare Workers.
!NOTE This package is opinionated! The choice of cryptographic algorithms, output format, etc. are not configurable. This package is more suitable for developers who would like to save time on writing boilerplates and don't have requirements on how the function is implemented/ its output format. Please read the documentation below before deciding to use this package whether or not.
Installation
npm install cf-workers-utilsUsage
Authentication
verifyToken(token: string, expectedTokenHash: string): Promise
Verifies a token with a expected token hash.
tokenThe token to be verified. Must be base64URL-encoded.expectedTokenHashThe expected SHA-512 hash of the token. Must be base64URL-encoded.
Returns whether the token matches the expected hash.
verifySignature(data: ArrayBuffer | ArrayBufferView, signature: string, publicKey: string): Promise
Verifies a signature of some data using a public key. Uses ECDSA with P-521 curve and SHA-512 hash.
dataThe data to be verified.signatureThe signature to be verified. Must be base64URL-encoded.publicKeyThe public key used for verification. Must be an ECDSA P-521 JSON Web Key (JWK) string.
Returns whether the signature is valid.
verifySignedURL(url: string, publicKey: string): Promise
Verifies a signed URL. Uses ECDSA with P-521 curve and SHA-512 hash.
urlThe URL to be verified. The signature should be included in thesigserach parameter.publicKeyThe public key used for verification. Must be an ECDSA P-521 JSON Web Key (JWK) string.
Returns whether the URL's signature is valid.
Binary Data Manipulation
isBase64URL(string: string): boolean
Checks if the inputted string is a valid base64URL string.
stringThe string to be checked.
Returns whether the string is a valid base64URL string.
uint8ArrayToString(bufferView: Uint8Array): string
Converts an Uint8Array into a Latin1 string.
bufferViewTheUint8Arrayto be converted.
Returns The converted Latin1 string.\
Throws TypeError if bufferView is not an Uint8Array.
stringToUint8Array(string: string): Uint8Array
Convert a Latin1 string into an Uint8Array.
stringThe Latin1 string to be converted.
Returns the converted Uint8Array.\
Throws RangeError if the string contains non-Latin1 character (code point higher than 255).
uint8ArrayToBase64URL(bufferView: Uint8Array): string
Converts an Uint8Array into a base64URL-encoded string.
bufferViewTheUint8Arrayto be converted.
Returns the converted base64URL-encoded string.
base64URLToUint8Array(string: string): Uint8Array
Convert an base64URL-encoded string into an Uint8Array.
stringThe base64URL-encoded string to be converted. Returns the convertedUint8Array.\ ThrowsRangeErrorif the string is empty or contains character not in the base64URL character set (i.e. does not match/^[0-9A-Za-z_-]+$/).
Response Creation
createResponse(body: Record<string, unknown> | null, status = 200, additionalHeaders: Record<string, string> = {}): Response
Creates a Response.
bodyThe body to be used in the response,nullif no body is needed.statusThe status code to be used in the response. Defaults to 200.additionalHeadersAdditional headers to be used int the response.'Content-Type': 'application/json'will be added automatically ifbodyis not null.
Returns the created Response, either a JSON response or an empty response.
createResponseFromError(error: Error, status = 500, additionalHeaders: Record<string, string> = {}): Response
Creates a Response from an Error.
errorThe error to be used to create the response. Its name and message will be included.statusThe status code to be used in the response. Defaults to 500.additionalHeadersAdditional headers to be used int the response.'Content-Type': 'application/json'is always added.
Returns The created Response, must be a JSON response in the folowing format:
{
"errorCode": "<value of error.name>",
"errorMessage": "<value of error.message>"
}Router
A itty-router like tiny router. It is designed to be a smaller version of IttyRouter, currently sized ~370 bytes when minified.
Difference between Router and IttyRouter
Router.fetchrequires a standard Request object instead ofRequestLike.Routeruses URL Pattern API for route pattern matching instead of regex.- Parsed URL is available under
request.parsedURLinRouter. It is the value returned byURLPattern.exec(url), whereurlis the URL of the incoming request (i.e.request.url). paramsandqueryis not available inRouterroute handlers.
createRouter<R, A, C>(base?: string): Router<R, A, C>
Creates an itty-router like tiny router.
baseBase URL of the router. If omitted, all patterns must be a full URL.RThe type of request with any additional properities to be defined on it, e.g., properities that will be injected by middleware.A(AdditionalArguments) An array or a tuple indicating the type of any additional arguments to be passed to the route handlers. For example if you would like to pass astringandnumberas additional arguments to the route handlers, pass in[string, number].C(CustomMethod) An union of any custom methods that are not included in the default type.
Returns the created router.
Router.(pattern: string, ..handlers: (request: R, ...additionalArguments: A) => unknown): Router<R, A, C>
Registers a route which match request with method methodName and URL matches pattern.
patternA pattern to be used to match the URL of the incoming request. See URL Pattern API for syntax.handlersHandlers which process the matched request. Handlers can act as a middleware and modify therequestobject. Returing a truthy value from a handler will prevent any handlers following it from executing and the value will be used as the returning value ofRouter.fetch.requestThe incomming request. It contains an extra fieldparsedURL.additionalArgumentsAdditional arguments passed toRouter.fetch.
Returns Router for chaining.
Router.fetch(request: R, ...additionalArguments: A): Promise
Handles an incoming fetch event.
requestAn incoming request. Can be extended by middlewares.additionalArgumentsAdditional arguments to be passed to the registered handlers (e.g. environment bindings).
Returns the return value of the first handler returning a truthy value.
Example
import type { Router, ExtendedRequest } from 'cf-workers-utils/router';
import { createRouter } from 'cf-workers-utils/router';
const router = createRouter<ExtendedRequest, [string]>('https://base.com');
const middleware = (request: ExtendedRequest, additionalArgument: string) => {
if (request.parsedURL?.pathname.groups.id === 'private') {
return `ID is private. Additional argument: ${additionalArgument}`;
}
}
router.get('/foo/:id', middleware, () => 'hello world!');
// Resolves to 'ID is private. Additional argument: extra value'
await router.fetch(new Request('https://base.com/foo/private'), 'extra value');You may refer to the itty-router docs for more examples.