Skip to content

Commit

Permalink
Add lib with JS build, typings.
Browse files Browse the repository at this point in the history
Finish README content.
Add query to test URL to ensure the query params are included in the redirect Location value.
Renamed `HTTP_REQUIRED` to `HTTPS_REQUIRED`.
  • Loading branch information
mattbishop committed Aug 16, 2022
1 parent acfdee0 commit 04cc027
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 9 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# fastify-https-always
This fastify plugin recognizes http requests and either redirects to https or disallows the request. Useful to ensure connections utilize secure HTTP connection URLs. The logic is very similar to the [express-ssl](https://github.com/jclem/express-ssl) plugin. It can examine the request headers to determine if a request has been forwarded from a TLS-terminating proxy, a common deployment model.
This fastify plugin recognizes http requests and either redirects to an https URL or disallows the request. Useful to ensure connections utilize secure HTTP connection URLs. The logic is very similar to the [express-ssl](https://github.com/jclem/express-ssl) plugin.

This plugin can examine the request headers to determine if a request has been forwarded from a TLS-terminating proxy, a common deployment model. It relies on fastify’s [trustProxy](https://www.fastify.io/docs/latest/Reference/Server/#trustproxy) setting to learn the protocol and host name of a request sent through a proxy, such as an API gateway or load balancer.

### Configuration

### fastify's trustProxy
This plugin has several optional configurations that can be used to change the behavior of the plugin. The following table lists these options for your configuration.

| Option | Default | Notes |
| ---------------- | ----------------------------------------------------- | ------------------------------------------------------------ |
| `enabled` | `true` | Enables the plugin. Useful in build systems where the plugin’s enabled state is driven by an environment variable. |
| `productionOnly` | `true` | Only enable this plugin in production environments. Checks Node’s `NODE_ENV` environment variable for the standard `production` value. |
| `redirect` | `true` | `http` requests will be redirected to the appropriate `https` service. If this config is false, then a `403 Forbidden` error is returned instead. |
| `httpsPort` | `undefined` (spec uses 443 as the default https port) | Use this value to change the https port used in the redirect Location header. |

10 changes: 10 additions & 0 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// <reference types="node" />
import { FastifyPluginOptions } from "fastify";
export interface HttpsAlwaysOptions extends FastifyPluginOptions {
enabled?: boolean;
productionOnly?: boolean;
redirect?: boolean;
httpsPort?: number;
}
declare const _default: import("fastify").FastifyPluginCallback<HttpsAlwaysOptions, import("http").Server>;
export default _default;
43 changes: 43 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const error_1 = __importDefault(require("@fastify/error"));
const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
const HTTPS_REQUIRED = (0, error_1.default)("FST_HTTPS_REQUIRED", "Please use HTTPS when communicating with this server.", 403);
function handleRequest(ctx, request, reply, next) {
const { port, redirect } = ctx;
const { hostname, protocol, url } = request;
if (protocol !== "https") {
if (redirect) {
const portIdx = hostname.lastIndexOf(":");
const host = portIdx > 0 ? hostname.substring(0, portIdx) : hostname;
const httpsUrl = `https://${host}${port}${url}`;
reply.redirect(301, httpsUrl);
}
else {
next(HTTPS_REQUIRED());
return;
}
}
next();
}
function plugin(fastify, opts, next) {
const { enabled = true, productionOnly = true, redirect = true, httpsPort } = opts;
if (enabled) {
const inProd = process.env.NODE_ENV === "production";
if (!productionOnly || inProd) {
const ctx = {
redirect,
port: httpsPort ? `:${httpsPort}` : ""
};
fastify.addHook("onRequest", (q, p, d) => handleRequest(ctx, q, p, d));
}
}
next();
}
exports.default = (0, fastify_plugin_1.default)(plugin, {
name: "fastify-https-always",
fastify: ">=3.x"
});
12 changes: 6 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import fp from "fastify-plugin"


export interface HttpsAlwaysOptions extends FastifyPluginOptions {
productionOnly?: boolean
enabled?: boolean
httpsPort?: number
productionOnly?: boolean
redirect?: boolean
httpsPort?: number
}


Expand All @@ -17,7 +17,7 @@ type HttpsAlwaysContext = {
}


const HTTP_REQUIRED = createError(
const HTTPS_REQUIRED = createError(
"FST_HTTPS_REQUIRED",
"Please use HTTPS when communicating with this server.",
403)
Expand Down Expand Up @@ -45,7 +45,7 @@ function handleRequest(ctx: HttpsAlwaysContext,
const httpsUrl = `https://${host}${port}${url}`
reply.redirect(301, httpsUrl)
} else {
next(HTTP_REQUIRED())
next(HTTPS_REQUIRED())
return
}
}
Expand All @@ -60,13 +60,13 @@ function plugin(fastify: FastifyInstance,
const {
enabled = true,
productionOnly = true,
httpsPort,
redirect = true,
httpsPort
} = opts

if (enabled) {
const inProd = process.env.NODE_ENV === "production"
if (!productionOnly || (productionOnly && inProd)) {
if (!productionOnly || inProd) {
const ctx: HttpsAlwaysContext = {
redirect,
port: httpsPort ? `:${httpsPort}` : ""
Expand Down
2 changes: 1 addition & 1 deletion test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import httpsAlwaysPlugin, {HttpsAlwaysOptions} from "../src"
// self-signed testing cert
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"

const URL = "/a/url"
const URL = "/a/url?qp=hi"

test("Tests for https-always", async (t) => {
const https = Fastify({
Expand Down

0 comments on commit 04cc027

Please sign in to comment.