Skip to content

Commit

Permalink
precompress middleware. close #664
Browse files Browse the repository at this point in the history
  • Loading branch information
oscarotero committed Oct 26, 2024
1 parent 95b612b commit 036b879
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 1 deletion.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Go to the `v1` branch to see the changelog of Lume 1.
- New plugin: `google_fonts` to download and self-host automatically fonts from Google Fonts.
- New plugin: `brotli` to compress files. [#681]
- New plugin: `gzip` to compress files. [#680]
- New `precompress` middleware, to serve precompressed files. [#664]

### Fixed
- Nav plugin: Breadcrumb with urls with CJK characters.
Expand Down Expand Up @@ -558,6 +559,7 @@ Go to the `v1` branch to see the changelog of Lume 1.
[#652]: https://github.com/lumeland/lume/issues/652
[#655]: https://github.com/lumeland/lume/issues/655
[#662]: https://github.com/lumeland/lume/issues/662
[#664]: https://github.com/lumeland/lume/issues/664
[#667]: https://github.com/lumeland/lume/issues/667
[#668]: https://github.com/lumeland/lume/issues/668
[#671]: https://github.com/lumeland/lume/issues/671
Expand All @@ -566,8 +568,8 @@ Go to the `v1` branch to see the changelog of Lume 1.
[#677]: https://github.com/lumeland/lume/issues/677
[#678]: https://github.com/lumeland/lume/issues/678
[#679]: https://github.com/lumeland/lume/issues/679
[#681]: https://github.com/lumeland/lume/issues/681
[#680]: https://github.com/lumeland/lume/issues/680
[#681]: https://github.com/lumeland/lume/issues/681

[Unreleased]: https://github.com/lumeland/lume/compare/v2.3.3...HEAD
[2.3.3]: https://github.com/lumeland/lume/compare/v2.3.2...v2.3.3
Expand Down
69 changes: 69 additions & 0 deletions middlewares/precompress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { merge } from "../core/utils/object.ts";
import { contentType } from "../deps/media_types.ts";
import { extname } from "../deps/path.ts";

import type { Middleware, RequestHandler } from "../core/server.ts";

/** The options to configure the middleware server */
export interface Options {
encodings: Record<string, string>;
}

export const defaults: Options = {
encodings: {
br: ".br",
gzip: ".gz",
},
};

export function preCompress(userOptions?: Options): Middleware {
const options = merge(defaults, userOptions);

return async function (
request: Request,
next: RequestHandler,
): Promise<Response> {
const accepted = new Set(
request.headers.get("Accept-Encoding")
?.split(",")
.map((encoding) => encoding.split(";").shift()?.trim())
.filter((encoding) => encoding),
);

if (!accepted.size) {
return next(request);
}

for (const [encoding, ext] of Object.entries(options.encodings)) {
if (!accepted.has(encoding)) {
continue;
}

const newUrl = new URL(request.url);
const initialExtension = newUrl.pathname.endsWith("/")
? ".html"
: extname(newUrl.pathname);
newUrl.pathname += newUrl.pathname.endsWith("/")
? `index.html${ext}`
: ext;
const compressedRequest = new Request(newUrl, request);
const response = await next(compressedRequest);

if (response.status >= 400) {
continue;
}

response.headers.set(
"Content-Type",
contentType(initialExtension) || "application/octet-stream",
);
response.headers.set("Content-Encoding", encoding);
response.headers.append("Vary", "Accept-Encoding");
return response;
}

return next(request);
};
}

export default preCompress;

0 comments on commit 036b879

Please sign in to comment.