@cloudflare/kv-asset-handler
Advanced tools
Comparing version 0.0.11 to 0.0.12
# Changelog | ||
## 0.0.12 | ||
- ### Features | ||
- **Add defaultMimeType option to getAssetFromKV - [mgrahamjo], [pull/121]** | ||
Some static website owners prefer not to create all of their web routes as directories containing index.html files. Instead, they prefer to create pages as extensionless HTML files. Providing a defaultMimeType option will allow users to set the Content-Type header for extensionless files to text/html, which will enable this use case. | ||
[mgrahamjo]: https://github.com/mgrahamjo | ||
[pull/121]: https://github.com/cloudflare/kv-asset-handler/pull/121 | ||
- **Add defaultMimeType to types - [shagamemnon], [pull/132]** | ||
Adds the newly added defaultMimeType to the exported types for this package. | ||
[pull/132]: https://github.com/cloudflare/kv-asset-handler/pull/132 | ||
- ### Fixes | ||
- **Fix text/* charset - [EatonZ], [pull/130]** | ||
Adds a missing `-` to the `utf-8` charset value in response mime types. | ||
[EatonZ]: https://github.com/EatonZ | ||
[pull/130]: https://github.com/cloudflare/kv-asset-handler/pull/130 | ||
- **Cache handling for HEAD requests - [klittlepage], [pull/141]** | ||
This PR skips caching for incoming HEAD requests, as they should not be able to be edge cached. | ||
[klittlepage]: https://github.com/klittlepage | ||
[pull/141]: https://github.com/cloudflare/kv-asset-handler/pull/141 | ||
- ### Maintenance | ||
- **Markdown linting/typos - [jbampton], [pull/123], [pull/125], [pull/126], [pull/127], [pull/128], [pull/129], [pull/131], [pull/134]** | ||
These PRs contain various typo fixes and linting of existing Markdown files in our documentation and CHANGELOG. | ||
[jbampton]: https://github.com/jbampton | ||
[pull/123]: https://github.com/cloudflare/kv-asset-handler/pull/123 | ||
[pull/125]: https://github.com/cloudflare/kv-asset-handler/pull/125 | ||
[pull/126]: https://github.com/cloudflare/kv-asset-handler/pull/126 | ||
[pull/127]: https://github.com/cloudflare/kv-asset-handler/pull/127 | ||
[pull/128]: https://github.com/cloudflare/kv-asset-handler/pull/128 | ||
[pull/129]: https://github.com/cloudflare/kv-asset-handler/pull/129 | ||
[pull/131]: https://github.com/cloudflare/kv-asset-handler/pull/131 | ||
[pull/134]: https://github.com/cloudflare/kv-asset-handler/pull/134 | ||
## 0.0.11 | ||
@@ -11,3 +60,3 @@ | ||
Now, `getAssetFromKV` sets an `ETag` header on all cachable assets before putting them in the Cache API, and therefore will return a `304` response when appropriate. | ||
Now, `getAssetFromKV` sets an `ETag` header on all cacheable assets before putting them in the Cache API, and therefore will return a `304` response when appropriate. | ||
@@ -70,8 +119,8 @@ [shagamemnon]: https://github.com/shagamemnon | ||
Prior to this PR, `getAssetFromKv` assumed extensionless requests (e.g. `/some-path`) would be set up to be served as the corresponding HTML file in storage (e.g. `some-path.html`). | ||
This fix checks the `ASSET_MANIFEST` for the extensionless file name _before_ appending the HTML extension. If the extensionless file exists (e.g. `some-path` exists as a key in the ASSET_MANIFEST) then we serve that file first. If the extensionless file does not exist, then the behavior does not change (e.g. it still looks for `some-path.html`). | ||
Prior to this PR, `getAssetFromKv` assumed extensionless requests (e.g. `/some-path`) would be set up to be served as the corresponding HTML file in storage (e.g. `some-path.html`). | ||
This fix checks the `ASSET_MANIFEST` for the extensionless file name _before_ appending the HTML extension. If the extensionless file exists (e.g. `some-path` exists as a key in the ASSET_MANIFEST) then we serve that file first. If the extensionless file does not exist, then the behavior does not change (e.g. it still looks for `some-path.html`). | ||
[victoriabernard92]: https://github.com/victoriabernard92 | ||
[cloudflare/wrangler/issues/980]: https://github.com/cloudflare/wrangler/issues/980 | ||
[pull/73]: https://github.com/cloudflare/kv-asset-handler/pull/73 | ||
[victoriabernard92]: https://github.com/victoriabernard92 | ||
[cloudflare/wrangler/issues/980]: https://github.com/cloudflare/wrangler/issues/980 | ||
[pull/73]: https://github.com/cloudflare/kv-asset-handler/pull/73 | ||
@@ -82,9 +131,9 @@ - ### Fixes | ||
This fixes an issue in `serveSinglePageApp` where the request.url is used as a string to retrieve static content. For example, | ||
if a query parameter was set, the URL lookup would break. This fix uses a parsed URL instead of the string and adjusts the README. | ||
This fixes an issue in `serveSinglePageApp` where the request.url is used as a string to retrieve static content. For example, | ||
if a query parameter was set, the URL lookup would break. This fix uses a parsed URL instead of the string and adjusts the README. | ||
[signalnerve]: https://github.com/signalnerve | ||
[sgiacosa]: https://github.com/sgiacosa | ||
[issue/72]: https://github.com/cloudflare/kv-asset-handler/issue/72 | ||
[pull/82]: https://github.com/cloudflare/kv-asset-handler/pull/82 | ||
[signalnerve]: https://github.com/signalnerve | ||
[sgiacosa]: https://github.com/sgiacosa | ||
[issue/72]: https://github.com/cloudflare/kv-asset-handler/issue/72 | ||
[pull/82]: https://github.com/cloudflare/kv-asset-handler/pull/82 | ||
@@ -97,7 +146,7 @@ ## 0.0.9 | ||
Added a `prepack` step that builds JavaScript files from the TypeScript source. This fixes previously broken `npm` publishes. | ||
Added a `prepack` step that builds JavaScript files from the TypeScript source. This fixes previously broken `npm` publishes. | ||
[victoriabernard92]: https://github.com/victoriabernard92 | ||
[issue/78]: https://github.com/cloudflare/kv-asset-handler/issue/78 | ||
[pull/79]: https://github.com/cloudflare/kv-asset-handler/pull/79 | ||
[victoriabernard92]: https://github.com/victoriabernard92 | ||
[issue/78]: https://github.com/cloudflare/kv-asset-handler/issue/78 | ||
[pull/79]: https://github.com/cloudflare/kv-asset-handler/pull/79 | ||
@@ -110,3 +159,3 @@ ## 0.0.8 | ||
Previously, `getAssetFromKv` would throw the same error type if anything went wrong. Now it will throw different error types so that clients can catch and differentiate them. | ||
Previously, `getAssetFromKv` would throw the same error type if anything went wrong. Now it will throw different error types so that clients can catch and differentiate them. | ||
For example, a 404 `NotFoundError` error implies nothing went wrong, the asset just didn't exist while | ||
@@ -124,7 +173,7 @@ a 500 `InternalError` means an expected variable was undefined. | ||
Previously, if you wanted to serve a video from Workers KV using `kv-asset-handler`, it would be broken on Safari due to its requirement that all videos support the [`Content-Range` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range). Cloudflare already has a feature that will handle these headers automatically, we just needed to take advantage of it by passing in a `Request` object to the [Cache API](https://developers.cloudflare.com/workers/reference/apis/cache/) rather than a URL string. | ||
Previously, if you wanted to serve a video from Workers KV using `kv-asset-handler`, it would be broken on Safari due to its requirement that all videos support the [`Content-Range` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range). Cloudflare already has a feature that will handle these headers automatically, we just needed to take advantage of it by passing in a `Request` object to the [Cache API](https://developers.cloudflare.com/workers/reference/apis/cache/) rather than a URL string. | ||
videos from not including the range headers. | ||
[victoriabernard92]: https://github.com/victoriabernard92 | ||
[shagamemnon]: https://github.com/shagamemnon | ||
[shagamemnon]: https://github.com/shagamemnon | ||
[issue/60]: https://github.com/cloudflare/kv-asset-handler/issues/60 | ||
@@ -143,3 +192,2 @@ [issue/63]: https://github.com/cloudflare/kv-asset-handler/issues/63 | ||
## 0.0.7 | ||
@@ -151,3 +199,3 @@ | ||
Some browser applications employ client-side routers that handle navigation in the browser rather than on the server. These applications will work as expected until a non-root URL is requested from the server. This PR adds a special handler, `serveSinglePageApp`, that maps all html requests to the root index.html. This is similar to setting a static asset route pattern in an Express.js app. | ||
Some browser applications employ client-side routers that handle navigation in the browser rather than on the server. These applications will work as expected until a non-root URL is requested from the server. This PR adds a special handler, `serveSinglePageApp`, that maps all HTML requests to the root index.html. This is similar to setting a static asset route pattern in an Express.js app. | ||
@@ -174,5 +222,5 @@ [ashleymichal]: https://github.com/ashleymichal | ||
- Don't use browser cache by default: Previously, `kv-asset-handler` would set a `Cache-Control` header on the response sent back from the Worker to the client. After this fix, the `Cache-Control` header will only be set if `options.cacheControl.browserTTL` is set by the caller. | ||
- Don't use browser cache by default: Previously, `kv-asset-handler` would set a `Cache-Control` header on the response sent back from the Worker to the client. After this fix, the `Cache-Control` header will only be set if `options.cacheControl.browserTTL` is set by the caller. | ||
- Set default edge caching to 2 days: Previously the default cache time for static assets was 100 days. This PR sets the default to 2 days. This can be overridden with `options.cacheControl.edgeTTL`. | ||
- Set default edge caching to 2 days: Previously the default cache time for static assets was 100 days. This PR sets the default to 2 days. This can be overridden with `options.cacheControl.edgeTTL`. | ||
@@ -179,0 +227,0 @@ [victoriabernard92]: https://github.com/victoriabernard92 |
@@ -119,3 +119,3 @@ # Contributor Covenant Code of Conduct | ||
version 2.0, available at | ||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. | ||
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>. | ||
@@ -128,3 +128,3 @@ Community Impact Guidelines were inspired by [Mozilla's code of conduct | ||
For answers to common questions about this code of conduct, see the FAQ at | ||
https://www.contributor-covenant.org/faq. Translations are available at | ||
https://www.contributor-covenant.org/translations. | ||
<https://www.contributor-covenant.org/faq>. Translations are available at | ||
<https://www.contributor-covenant.org/translations>. |
@@ -15,3 +15,3 @@ import { Options, CacheControl, MethodNotAllowedError, NotFoundError, InternalError } from './types'; | ||
* maps the path of incoming request to /index.html if it evaluates to | ||
* any html file. | ||
* any HTML file. | ||
* @param {Request} request incoming request | ||
@@ -21,3 +21,3 @@ */ | ||
/** | ||
* takes the path of the incoming request, gathers the approriate cotent from KV, and returns | ||
* takes the path of the incoming request, gathers the appropriate content from KV, and returns | ||
* the response | ||
@@ -24,0 +24,0 @@ * |
@@ -39,7 +39,8 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.InternalError = exports.NotFoundError = exports.MethodNotAllowedError = exports.serveSinglePageApp = exports.mapRequestToAsset = exports.getAssetFromKV = void 0; | ||
var mime = require("mime"); | ||
var types_1 = require("./types"); | ||
exports.MethodNotAllowedError = types_1.MethodNotAllowedError; | ||
exports.NotFoundError = types_1.NotFoundError; | ||
exports.InternalError = types_1.InternalError; | ||
Object.defineProperty(exports, "MethodNotAllowedError", { enumerable: true, get: function () { return types_1.MethodNotAllowedError; } }); | ||
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return types_1.NotFoundError; } }); | ||
Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return types_1.InternalError; } }); | ||
/** | ||
@@ -71,3 +72,3 @@ * maps the path of incoming request to the request pathKey to look up | ||
* maps the path of incoming request to /index.html if it evaluates to | ||
* any html file. | ||
* any HTML file. | ||
* @param {Request} request incoming request | ||
@@ -99,3 +100,3 @@ */ | ||
/** | ||
* takes the path of the incoming request, gathers the approriate cotent from KV, and returns | ||
* takes the path of the incoming request, gathers the appropriate content from KV, and returns | ||
* the response | ||
@@ -121,2 +122,3 @@ * | ||
cacheControl: defaultCacheControl, | ||
defaultMimeType: 'text/plain', | ||
}, options); | ||
@@ -154,5 +156,5 @@ request = event.request; | ||
cache = caches.default; | ||
mimeType = mime.getType(pathKey) || 'text/plain'; | ||
mimeType = mime.getType(pathKey) || options.defaultMimeType; | ||
if (mimeType.startsWith('text')) { | ||
mimeType += '; charset=utf8'; | ||
mimeType += '; charset=utf-8'; | ||
} | ||
@@ -182,3 +184,5 @@ shouldEdgeCache = false // false if storing in KV by raw file path i.e. no hash | ||
// override shouldEdgeCache if options say to bypassCache | ||
if (options.cacheControl.bypassCache || options.cacheControl.edgeTTL === null) { | ||
if (options.cacheControl.bypassCache || | ||
options.cacheControl.edgeTTL === null || | ||
request.method == 'HEAD') { | ||
shouldEdgeCache = false; | ||
@@ -185,0 +189,0 @@ } |
@@ -39,2 +39,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.sleep = exports.mockGlobal = exports.mockCaches = exports.mockManifest = exports.mockKV = exports.getEvent = void 0; | ||
var makeServiceWorkerEnv = require('service-worker-mock'); | ||
@@ -41,0 +42,0 @@ var HASH = '123HASHBROWN'; |
@@ -11,2 +11,3 @@ export declare type CacheControl = { | ||
mapRequestToAsset: (req: Request) => Request; | ||
defaultMimeType: string; | ||
}; | ||
@@ -13,0 +14,0 @@ export declare class KVError extends Error { |
@@ -16,2 +16,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.InternalError = exports.NotFoundError = exports.MethodNotAllowedError = exports.KVError = void 0; | ||
var KVError = /** @class */ (function (_super) { | ||
@@ -18,0 +19,0 @@ __extends(KVError, _super); |
{ | ||
"name": "@cloudflare/kv-asset-handler", | ||
"version": "0.0.11", | ||
"version": "0.0.12", | ||
"description": "Routes requests to KV assets", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
# @cloudflare/kv-asset-handler | ||
* [Installation](#installation) | ||
@@ -40,3 +41,2 @@ * [Usage](#usage) | ||
#### Example | ||
@@ -51,2 +51,3 @@ | ||
Known errors to be thrown are: | ||
- MethodNotAllowedError | ||
@@ -148,3 +149,2 @@ - NotFoundError | ||
#### `ASSET_NAMESPACE` | ||
@@ -156,3 +156,3 @@ | ||
It is further assumed that this namespace consists of static assets such as html, css, javascript, or image files, keyed off of a relative path that roughly matches the assumed url pathname of the incoming request. | ||
It is further assumed that this namespace consists of static assets such as HTML, CSS, JavaScript, or image files, keyed off of a relative path that roughly matches the assumed URL pathname of the incoming request. | ||
@@ -176,2 +176,10 @@ ``` | ||
#### `defaultMimeType` (optional) | ||
type: string | ||
This is the mime type that will be used for files with unrecognized or missing extensions. The default value is `'text/plain'`. | ||
If you are serving a static site and would like to use extensionless HTML files instead of index.html files, set this to `'text/html'`. | ||
# Helper functions | ||
@@ -185,3 +193,3 @@ | ||
Takes any path that ends in `/` or evaluates to an html file and appends `index.html` or `/index.html` for lookup in your Workers KV namespace. | ||
Takes any path that ends in `/` or evaluates to an HTML file and appends `index.html` or `/index.html` for lookup in your Workers KV namespace. | ||
@@ -205,2 +213,3 @@ ## `serveSinglePageApp` | ||
Resources served with an `etag` allow browsers to use the `if-none-match` request header to make conditional requests for that resource in the future. This has two major benefits: | ||
* When a request's `if-none-match` value matches the `etag` of the resource in Cloudflare cache, Cloudflare will send a `304 Not Modified` response without a body, saving bandwidth. | ||
@@ -212,2 +221,3 @@ * Changes to a file on the server are immediately reflected in the browser - even when the cache control directive `max-age` is unexpired. | ||
To turn `etags` **off**, you must bypass cache: | ||
```js | ||
@@ -214,0 +224,0 @@ /* Turn etags off */ |
@@ -59,3 +59,3 @@ # Release Checklist | ||
```console | ||
$ git push --delete origin tagname | ||
git push --delete origin tagname | ||
``` | ||
@@ -68,3 +68,3 @@ | ||
```console | ||
$ git tag --delete vX.X.X | ||
git tag --delete vX.X.X | ||
``` |
@@ -34,3 +34,3 @@ import * as mime from 'mime' | ||
* maps the path of incoming request to /index.html if it evaluates to | ||
* any html file. | ||
* any HTML file. | ||
* @param {Request} request incoming request | ||
@@ -64,3 +64,3 @@ */ | ||
/** | ||
* takes the path of the incoming request, gathers the approriate cotent from KV, and returns | ||
* takes the path of the incoming request, gathers the appropriate content from KV, and returns | ||
* the response | ||
@@ -83,2 +83,3 @@ * | ||
cacheControl: defaultCacheControl, | ||
defaultMimeType: 'text/plain', | ||
}, | ||
@@ -123,5 +124,5 @@ options, | ||
const cache = caches.default | ||
let mimeType = mime.getType(pathKey) || 'text/plain' | ||
let mimeType = mime.getType(pathKey) || options.defaultMimeType | ||
if (mimeType.startsWith('text')) { | ||
mimeType += '; charset=utf8' | ||
mimeType += '; charset=utf-8' | ||
} | ||
@@ -159,6 +160,10 @@ | ||
// override shouldEdgeCache if options say to bypassCache | ||
if (options.cacheControl.bypassCache || options.cacheControl.edgeTTL === null) { | ||
if ( | ||
options.cacheControl.bypassCache || | ||
options.cacheControl.edgeTTL === null || | ||
request.method == 'HEAD' | ||
) { | ||
shouldEdgeCache = false | ||
} | ||
// only set max-age if explictly passed in a number as an arg | ||
// only set max-age if explicitly passed in a number as an arg | ||
const shouldSetBrowserCache = typeof options.cacheControl.browserTTL === 'number' | ||
@@ -165,0 +170,0 @@ |
@@ -10,3 +10,4 @@ export type CacheControl = { | ||
ASSET_MANIFEST: Object | string | ||
mapRequestToAsset: (req: Request) => Request | ||
mapRequestToAsset: (req: Request) => Request, | ||
defaultMimeType: string | ||
} | ||
@@ -13,0 +14,0 @@ |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
139075
2200
225