@dwp/govuk-casa 8.2.1 → 8.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/casa.d.ts +4 -0
- package/dist/casa.js +1 -0
- package/dist/lib/configuration-ingestor.d.ts +3 -4
- package/dist/lib/configuration-ingestor.js +6 -10
- package/dist/lib/configure.js +6 -51
- package/dist/middleware/strip-proxy-path.d.ts +4 -0
- package/dist/middleware/strip-proxy-path.js +52 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [8.2.2](https://github.com/dwp/govuk-casa/compare/8.2.1...8.2.2) (2022-05-23)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* escape from sticky edit on return to edit origin in a proxied app ([9303af1](https://github.com/dwp/govuk-casa/commit/9303af140ec383801741d50f3404fd7cfe930d90))
|
|
11
|
+
|
|
5
12
|
### [8.2.1](https://github.com/dwp/govuk-casa/compare/8.2.0...8.2.1) (2022-05-20)
|
|
6
13
|
|
|
7
14
|
|
package/dist/casa.d.ts
CHANGED
|
@@ -122,6 +122,10 @@ export type MutableRouter = import('./lib/index').MutableRouter;
|
|
|
122
122
|
* Configuration options
|
|
123
123
|
*/
|
|
124
124
|
export type ConfigurationOptions = {
|
|
125
|
+
/**
|
|
126
|
+
* Prefix for all URLS in browser address bar
|
|
127
|
+
*/
|
|
128
|
+
mountUrl?: string | undefined;
|
|
125
129
|
/**
|
|
126
130
|
* Template directories
|
|
127
131
|
*/
|
package/dist/casa.js
CHANGED
|
@@ -126,6 +126,7 @@ exports.nunjucksFilters = nunjucksFilters;
|
|
|
126
126
|
* Configure some middleware for use in creating a new CASA app.
|
|
127
127
|
*
|
|
128
128
|
* @typedef {object} ConfigurationOptions Configuration options
|
|
129
|
+
* @property {string} [mountUrl] Prefix for all URLS in browser address bar
|
|
129
130
|
* @property {string[]} [views=[]] Template directories
|
|
130
131
|
* @property {SessionOptions} [session] Session configuration
|
|
131
132
|
* @property {Page[]} [pages=[]] Pages the represent waypoints
|
|
@@ -28,12 +28,11 @@ export function validateI18nLocales(locales?: any[]): any[];
|
|
|
28
28
|
/**
|
|
29
29
|
* Validates and sanitises mount url.
|
|
30
30
|
*
|
|
31
|
-
* @param {string} mountUrl
|
|
32
|
-
* @param {string} name Name of the URL type (Mount URL, or Proxy Mount URL).
|
|
31
|
+
* @param {string} mountUrl Prefix for all URLs in the browser address bar
|
|
33
32
|
* @throws {SyntaxError} For invalid URL.
|
|
34
|
-
* @returns {string} Sanitised URL.
|
|
33
|
+
* @returns {string|undefined} Sanitised URL.
|
|
35
34
|
*/
|
|
36
|
-
export function validateMountUrl(mountUrl: string
|
|
35
|
+
export function validateMountUrl(mountUrl: string): string | undefined;
|
|
37
36
|
/**
|
|
38
37
|
* Validates and sanitises sessions object.
|
|
39
38
|
*
|
|
@@ -75,17 +75,16 @@ exports.validateI18nLocales = validateI18nLocales;
|
|
|
75
75
|
/**
|
|
76
76
|
* Validates and sanitises mount url.
|
|
77
77
|
*
|
|
78
|
-
* @param {string} mountUrl
|
|
79
|
-
* @param {string} name Name of the URL type (Mount URL, or Proxy Mount URL).
|
|
78
|
+
* @param {string} mountUrl Prefix for all URLs in the browser address bar
|
|
80
79
|
* @throws {SyntaxError} For invalid URL.
|
|
81
|
-
* @returns {string} Sanitised URL.
|
|
80
|
+
* @returns {string|undefined} Sanitised URL.
|
|
82
81
|
*/
|
|
83
|
-
function validateMountUrl(mountUrl
|
|
82
|
+
function validateMountUrl(mountUrl) {
|
|
84
83
|
if (typeof mountUrl === 'undefined') {
|
|
85
|
-
return
|
|
84
|
+
return undefined;
|
|
86
85
|
}
|
|
87
86
|
if (!mountUrl.match(/\/$/)) {
|
|
88
|
-
throw new SyntaxError(
|
|
87
|
+
throw new SyntaxError('mountUrl must include a trailing slash (/)');
|
|
89
88
|
}
|
|
90
89
|
return mountUrl;
|
|
91
90
|
}
|
|
@@ -382,10 +381,7 @@ function ingest(config = {}) {
|
|
|
382
381
|
dirs: validateI18nDirs(i18n.dirs),
|
|
383
382
|
locales: validateI18nLocales(i18n.locales),
|
|
384
383
|
})),
|
|
385
|
-
//
|
|
386
|
-
// This will be removed in next major version
|
|
387
|
-
//
|
|
388
|
-
// Public URL from which the app will be served
|
|
384
|
+
// URL that will prefix all URLs in the browser address bar
|
|
389
385
|
mountUrl: validateMountUrl(config.mountUrl),
|
|
390
386
|
// Session
|
|
391
387
|
session: validateSessionObject(config.session, (session) => ({
|
package/dist/lib/configure.js
CHANGED
|
@@ -16,6 +16,7 @@ const nunjucks_js_1 = __importDefault(require("./nunjucks.js"));
|
|
|
16
16
|
const static_js_1 = __importDefault(require("../routes/static.js"));
|
|
17
17
|
const ancillary_js_1 = __importDefault(require("../routes/ancillary.js"));
|
|
18
18
|
const journey_js_1 = __importDefault(require("../routes/journey.js"));
|
|
19
|
+
const strip_proxy_path_js_1 = __importDefault(require("../middleware/strip-proxy-path.js"));
|
|
19
20
|
const pre_js_1 = __importDefault(require("../middleware/pre.js"));
|
|
20
21
|
const post_js_1 = __importDefault(require("../middleware/post.js"));
|
|
21
22
|
const session_js_1 = __importDefault(require("../middleware/session.js"));
|
|
@@ -23,8 +24,6 @@ const i18n_js_1 = __importDefault(require("../middleware/i18n.js"));
|
|
|
23
24
|
const data_js_1 = __importDefault(require("../middleware/data.js"));
|
|
24
25
|
const body_parser_js_1 = __importDefault(require("../middleware/body-parser.js"));
|
|
25
26
|
const csrf_js_1 = __importDefault(require("../middleware/csrf.js"));
|
|
26
|
-
const logger_js_1 = __importDefault(require("./logger.js"));
|
|
27
|
-
const log = (0, logger_js_1.default)('lib:configure');
|
|
28
27
|
/**
|
|
29
28
|
* @typedef {import('../casa').ConfigurationOptions} ConfigurationOptions
|
|
30
29
|
*/
|
|
@@ -48,7 +47,7 @@ function configure(config = {}) {
|
|
|
48
47
|
plugin.configure(config);
|
|
49
48
|
});
|
|
50
49
|
// Extract config
|
|
51
|
-
const { mountUrl
|
|
50
|
+
const { mountUrl, views = [], session = {
|
|
52
51
|
secret: 'secret',
|
|
53
52
|
name: 'casasession',
|
|
54
53
|
secure: false,
|
|
@@ -134,54 +133,10 @@ function configure(config = {}) {
|
|
|
134
133
|
const mount = (app, { route = '/' } = {}) => {
|
|
135
134
|
nunjucksEnv.express(app);
|
|
136
135
|
app.set('view engine', 'njk');
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
// In some cases, the URL on which `app` instance is mounted might include a
|
|
143
|
-
// proxy path so that it can handle incoming requests that have had a path
|
|
144
|
-
// prepended to it by an intermediary, such as nginx. This would be common
|
|
145
|
-
// in a hosting environment that serves several separate applications.
|
|
146
|
-
//
|
|
147
|
-
// This bit of middleware removes that proxy path segment from the request
|
|
148
|
-
// so that all subsequent middleware behave as if it was never present.
|
|
149
|
-
//
|
|
150
|
-
// e.g. Where the proxy path is `my-proxy`, then a request to
|
|
151
|
-
// `/my-proxy/app` will be seen as `/app` in all subsequent middleware, and
|
|
152
|
-
// all URLs generated for the browser will use `/app`.
|
|
153
|
-
//
|
|
154
|
-
// Using `config.mountUrl` rather than `mountUrl` here to test whether the
|
|
155
|
-
// consumer explicitly set a `mountUrl`, in which case we're dealing with
|
|
156
|
-
// backwards-compatibility mode.
|
|
157
|
-
//
|
|
158
|
-
// This intervention would not be needed for apps that omit `mountUrl` as if
|
|
159
|
-
// so, it's assumed they're following the guidance for setting up a proxy
|
|
160
|
-
// as described in `docs/guides/setup-behind-a-proxy.md`.
|
|
161
|
-
if (config.mountUrl) {
|
|
162
|
-
log.warn('[DEPRECATION WARNING] Using configuration attribute, mountUrl. This will be removed in an upcoming major version');
|
|
163
|
-
app.use((req, res, next) => {
|
|
164
|
-
// Mimic what the `docs/guides/setup-behind-a-proxy.md` guidance
|
|
165
|
-
// recommends for stripping off any proxy prefixes to leave just the
|
|
166
|
-
// "mountUrl" remaining.
|
|
167
|
-
const originalBaseUrl = req.baseUrl;
|
|
168
|
-
req.baseUrl = mountUrl.replace(/\/$/, '');
|
|
169
|
-
// If the app has been mounted directly on the specific `mountUrl`, then
|
|
170
|
-
// there's nothing we need to do and can let this request pass-through.
|
|
171
|
-
if (req.baseUrl === originalBaseUrl) {
|
|
172
|
-
next();
|
|
173
|
-
}
|
|
174
|
-
else if (req.__CASA_BASE_URL_REWRITTEN__) {
|
|
175
|
-
delete req.__CASA_BASE_URL_REWRITTEN__;
|
|
176
|
-
next();
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
// Issuing this call will re-run this same middleware, so we use this
|
|
180
|
-
// `__CASA_BASE_URL_REWRITTEN__` flag to prevent recursion.
|
|
181
|
-
req.__CASA_BASE_URL_REWRITTEN__ = true;
|
|
182
|
-
req.app.handle(req, res, next);
|
|
183
|
-
}
|
|
184
|
-
});
|
|
136
|
+
// If a `mountUrl` has been defined, then we're potentially in "proxy mode",
|
|
137
|
+
// in which we strip the proxy path prefix from the incoming request URLs.
|
|
138
|
+
if (mountUrl) {
|
|
139
|
+
app.use((0, strip_proxy_path_js_1.default)({ mountUrl }));
|
|
185
140
|
}
|
|
186
141
|
// Attach a handler to redirect requests for `/` to the first waypoint in
|
|
187
142
|
// the plan
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Strip any "proxy path" prefix present on the request URL
|
|
3
|
+
//
|
|
4
|
+
// The default "mountUrl" will be match whatever path that the CASA app
|
|
5
|
+
// instance will be mounted onto. So if you mount on `/a/b/c` then all
|
|
6
|
+
// URLs generated for the browser will be prefixed with `/a/b/c`.
|
|
7
|
+
//
|
|
8
|
+
// Defining a `mountUrl` will change that behaviour into a "proxy mode".
|
|
9
|
+
// This mode assumes you have a forwarding proxy that will alter
|
|
10
|
+
// the incoming request paths from `mountUrl` to the original path you
|
|
11
|
+
// have mounted this CASA app instance onto.
|
|
12
|
+
//
|
|
13
|
+
// For example, if you mount the app on `/a/b/c/x`, but want the browser
|
|
14
|
+
// URLs to just use the `/x` prefix, then pass a `mountUrl` of `/x`.
|
|
15
|
+
//
|
|
16
|
+
// See docs in `docs/guides/setup-behind-a-proxy.md`
|
|
17
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
const logger_js_1 = __importDefault(require("../lib/logger.js"));
|
|
22
|
+
const log = (0, logger_js_1.default)('casa:middleware:strip-proxy-path');
|
|
23
|
+
exports.default = ({ mountUrl = '/', }) => [
|
|
24
|
+
(req, res, next) => {
|
|
25
|
+
// Assume everything before `mountUrl` is the proxy path prefix and remove it
|
|
26
|
+
const originalBaseUrl = req.baseUrl;
|
|
27
|
+
req.baseUrl = mountUrl.replace(/\/$/, '');
|
|
28
|
+
// If the app has been mounted directly on the specific `mountUrl`, then
|
|
29
|
+
// there's nothing we need to do and can let this request pass-through.
|
|
30
|
+
if (req.baseUrl === originalBaseUrl) {
|
|
31
|
+
next();
|
|
32
|
+
}
|
|
33
|
+
else if (req.__CASA_BASE_URL_REWRITTEN__) {
|
|
34
|
+
delete req.__CASA_BASE_URL_REWRITTEN__;
|
|
35
|
+
next();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Strip the proxy path prefix from the original URL so that
|
|
39
|
+
// subsequnt middleware sees the URL path as though proxy wasn't there.
|
|
40
|
+
// req.url will already have the proxy prefix and mountUrl removed.
|
|
41
|
+
/* eslint-disable security/detect-non-literal-regexp */
|
|
42
|
+
log.trace(`req.originalUrl before proxy stripping: ${req.originalUrl}`);
|
|
43
|
+
req.originalUrl = req.originalUrl.replace(new RegExp(`^/.+?${mountUrl}`), mountUrl);
|
|
44
|
+
log.trace(`req.originalUrl after proxy stripping: ${req.originalUrl}`);
|
|
45
|
+
/* eslint-enable security/detect-non-literal-regexp */
|
|
46
|
+
// Issuing this call will re-run this same middleware, so we use this
|
|
47
|
+
// `__CASA_BASE_URL_REWRITTEN__` flag to prevent recursion.
|
|
48
|
+
req.__CASA_BASE_URL_REWRITTEN__ = true;
|
|
49
|
+
req.app.handle(req, res, next);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
];
|