i18next-http-middleware 3.9.1 → 3.9.3

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/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Actions](https://github.com/i18next/i18next-http-middleware/workflows/node/badge.svg)](https://github.com/i18next/i18next-http-middleware/actions?query=workflow%3Anode)
4
4
  [![Actions deno](https://github.com/i18next/i18next-http-middleware/workflows/deno/badge.svg)](https://github.com/i18next/i18next-http-middleware/actions?query=workflow%3Adeno)
5
- [![Travis](https://img.shields.io/travis/i18next/i18next-http-middleware/master.svg?style=flat-square)](https://travis-ci.org/i18next/i18next-http-middleware)
6
5
  [![npm version](https://img.shields.io/npm/v/i18next-http-middleware.svg?style=flat-square)](https://www.npmjs.com/package/i18next-http-middleware)
7
6
 
8
7
  This is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.
@@ -12,8 +12,7 @@ var _header = _interopRequireDefault(require("./languageLookups/header.js"));
12
12
  var _session = _interopRequireDefault(require("./languageLookups/session.js"));
13
13
  var _httpFunctions = require("./httpFunctions.js");
14
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
16
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
17
16
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
18
17
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
19
18
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
package/cjs/index.d.ts CHANGED
@@ -185,3 +185,34 @@ export class LanguageDetector implements i18next.Module {
185
185
  caches: LanguageDetectorCaches
186
186
  ): void;
187
187
  }
188
+
189
+
190
+ export interface HapiPlugin<TOptions = any> {
191
+ name: string;
192
+ version: string;
193
+ register: (
194
+ server: {
195
+ ext: (
196
+ event: string,
197
+ method: (request: any, h: any) => any
198
+ ) => void;
199
+ },
200
+ options: TOptions & HandleOptions & { i18next?: I18next }
201
+ ) => void;
202
+ }
203
+
204
+ export const hapiPlugin: HapiPlugin;
205
+
206
+ declare const middleware: {
207
+ plugin: typeof plugin;
208
+ hapiPlugin: typeof hapiPlugin;
209
+ koaPlugin: typeof koaPlugin;
210
+ freshPlugin: typeof freshPlugin;
211
+ handle: typeof handle;
212
+ getResourcesHandler: typeof getResourcesHandler;
213
+ missingKeyHandler: typeof missingKeyHandler;
214
+ addRoute: typeof addRoute;
215
+ LanguageDetector: typeof LanguageDetector;
216
+ };
217
+
218
+ export default middleware;
package/cjs/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
@@ -18,14 +17,15 @@ var utils = _interopRequireWildcard(require("./utils.js"));
18
17
  var _LanguageDetector = _interopRequireDefault(require("./LanguageDetector.js"));
19
18
  var _httpFunctions = require("./httpFunctions.js");
20
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
22
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
21
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
23
22
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
24
23
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
25
24
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
26
25
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
27
26
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
28
- function _regeneratorRuntime() { "use strict"; _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
27
+ function _regenerator() { var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
28
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
29
29
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
30
30
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
31
31
  var LanguageDetector = exports.LanguageDetector = _LanguageDetector.default;
@@ -93,7 +93,7 @@ function handle(i18next) {
93
93
  res.locals.resolvedLanguage = i18n.resolvedLanguage;
94
94
  }
95
95
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
96
- options.setHeader(res, 'Content-Language', utils.escape(lng));
96
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng));
97
97
  }
98
98
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng);
99
99
  req.resolvedLanguage = i18n.resolvedLanguage;
@@ -107,7 +107,7 @@ function handle(i18next) {
107
107
  }
108
108
  req.language = req.locale = req.lng = lng;
109
109
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
110
- options.setHeader(res, 'Content-Language', utils.escape(lng));
110
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng));
111
111
  }
112
112
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng);
113
113
  req.resolvedLanguage = i18n.resolvedLanguage;
@@ -148,20 +148,19 @@ function plugin(instance, options, next) {
148
148
  function koaPlugin(i18next, options) {
149
149
  var middleware = handle(i18next, options);
150
150
  return function () {
151
- var _koaMiddleware = _asyncToGenerator(_regeneratorRuntime().mark(function _callee(ctx, next) {
152
- return _regeneratorRuntime().wrap(function _callee$(_context) {
153
- while (1) switch (_context.prev = _context.next) {
151
+ var _koaMiddleware = _asyncToGenerator(_regenerator().m(function _callee(ctx, next) {
152
+ return _regenerator().w(function (_context) {
153
+ while (1) switch (_context.n) {
154
154
  case 0:
155
- _context.next = 2;
155
+ _context.n = 1;
156
156
  return new Promise(function (resolve) {
157
157
  return middleware(ctx, ctx, resolve);
158
158
  });
159
- case 2:
160
- _context.next = 4;
159
+ case 1:
160
+ _context.n = 2;
161
161
  return next();
162
- case 4:
163
- case "end":
164
- return _context.stop();
162
+ case 2:
163
+ return _context.a(2);
165
164
  }
166
165
  }, _callee);
167
166
  }));
@@ -173,10 +172,10 @@ function koaPlugin(i18next, options) {
173
172
  }
174
173
  function freshPlugin(i18next, options) {
175
174
  return function () {
176
- var _ref = _asyncToGenerator(_regeneratorRuntime().mark(function _callee2(ctx) {
175
+ var _ref = _asyncToGenerator(_regenerator().m(function _callee2(ctx) {
177
176
  var placeholder, resp;
178
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
179
- while (1) switch (_context2.prev = _context2.next) {
177
+ return _regenerator().w(function (_context2) {
178
+ while (1) switch (_context2.n) {
180
179
  case 0:
181
180
  handle(i18next, _objectSpread(_objectSpread({}, options), {}, {
182
181
  attachLocals: true
@@ -189,15 +188,12 @@ function freshPlugin(i18next, options) {
189
188
  ctx.state.languages = ctx.req.languages;
190
189
  placeholder = ctx.state.res;
191
190
  delete ctx.state.res;
192
- _context2.next = 11;
191
+ _context2.n = 1;
193
192
  return ctx.next();
194
- case 11:
195
- resp = _context2.sent;
193
+ case 1:
194
+ resp = _context2.v;
196
195
  resp.headers.set('Content-Language', placeholder.headers.get('Content-Language'));
197
- return _context2.abrupt("return", resp);
198
- case 14:
199
- case "end":
200
- return _context2.stop();
196
+ return _context2.a(2, resp);
201
197
  }
202
198
  }, _callee2);
203
199
  }));
@@ -248,6 +244,8 @@ function getResourcesHandler(i18next) {
248
244
  languages = options.getParams(req)[options.lngParam || 'lng'] ? options.getParams(req)[options.lngParam || 'lng'].split(' ') : [];
249
245
  namespaces = options.getParams(req)[options.nsParam || 'ns'] ? options.getParams(req)[options.nsParam || 'ns'].split(' ') : [];
250
246
  }
247
+ languages = languages.filter(utils.isSafeIdentifier);
248
+ namespaces = namespaces.filter(utils.isSafeIdentifier);
251
249
  namespaces.forEach(function (ns) {
252
250
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
253
251
  i18next.options.ns.push(ns);
@@ -280,22 +278,26 @@ function missingKeyHandler(i18next) {
280
278
  return options.send(res, 'i18next-express-middleware:: no backend configured');
281
279
  }
282
280
  var body = options.getBody(req);
281
+ var saveMissingKeys = function saveMissingKeys(src) {
282
+ if (!src || _typeof(src) !== 'object') return;
283
+ for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
284
+ var m = _Object$keys[_i];
285
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue;
286
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
287
+ }
288
+ };
283
289
  if (typeof body === 'function') {
284
290
  var promise = body();
285
291
  if (promise && typeof promise.then === 'function') {
286
292
  return new Promise(function (resolve) {
287
293
  promise.then(function (b) {
288
- for (var m in b) {
289
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m]);
290
- }
294
+ saveMissingKeys(b);
291
295
  resolve(options.send(res, 'ok'));
292
296
  });
293
297
  });
294
298
  }
295
299
  }
296
- for (var m in body) {
297
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m]);
298
- }
300
+ saveMissingKeys(body);
299
301
  return options.send(res, 'ok');
300
302
  };
301
303
  }
@@ -84,6 +84,8 @@ var _default = exports.default = {
84
84
  sameSite: options.cookieSameSite
85
85
  };
86
86
  if (options.cookieSecure) cookieOptions.secure = options.cookieSecure;
87
+ var sameSiteNormalised = typeof cookieOptions.sameSite === 'string' ? cookieOptions.sameSite.toLowerCase() : cookieOptions.sameSite;
88
+ if (sameSiteNormalised === 'none') cookieOptions.secure = true;
87
89
  var existingCookie = options.getHeader(res, 'set-cookie') || options.getHeader(res, 'Set-Cookie') || [];
88
90
  if (typeof existingCookie === 'string') existingCookie = [existingCookie];
89
91
  if (!Array.isArray(existingCookie)) existingCookie = [];
package/cjs/utils.js CHANGED
@@ -3,12 +3,25 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.UNSAFE_KEYS = void 0;
6
7
  exports.defaults = defaults;
7
8
  exports.escape = escape;
8
9
  exports.extend = extend;
9
10
  exports.hasXSS = hasXSS;
11
+ exports.isSafeIdentifier = isSafeIdentifier;
10
12
  exports.removeLngFromUrl = removeLngFromUrl;
13
+ exports.sanitizeHeaderValue = sanitizeHeaderValue;
11
14
  exports.setPath = setPath;
15
+ var UNSAFE_KEYS = exports.UNSAFE_KEYS = ['__proto__', 'constructor', 'prototype'];
16
+ function isSafeIdentifier(v) {
17
+ if (typeof v !== 'string') return false;
18
+ if (v.length === 0 || v.length > 128) return false;
19
+ if (UNSAFE_KEYS.indexOf(v) > -1) return false;
20
+ if (v.indexOf('..') > -1) return false;
21
+ if (v.indexOf('/') > -1 || v.indexOf('\\') > -1) return false;
22
+ if (/[\x00-\x1F\x7F]/.test(v)) return false;
23
+ return true;
24
+ }
12
25
  function setPath(object, path, newValue) {
13
26
  var stack;
14
27
  if (typeof path !== 'string') stack = [].concat(path);
@@ -16,11 +29,13 @@ function setPath(object, path, newValue) {
16
29
  while (stack.length > 1) {
17
30
  var _key = stack.shift();
18
31
  if (_key.indexOf('###') > -1) _key = _key.replace(/###/g, '.');
32
+ if (UNSAFE_KEYS.indexOf(_key) > -1) return;
19
33
  if (!object[_key]) object[_key] = {};
20
34
  object = object[_key];
21
35
  }
22
36
  var key = stack.shift();
23
37
  if (key.indexOf('###') > -1) key = key.replace(/###/g, '.');
38
+ if (UNSAFE_KEYS.indexOf(key) > -1) return;
24
39
  object[key] = newValue;
25
40
  }
26
41
  var arr = [];
@@ -62,9 +77,13 @@ function removeLngFromUrl(url, lookupFromPathIndex) {
62
77
  function escape(str) {
63
78
  return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\//g, '&#x2F;').replace(/\\/g, '&#x5C;').replace(/`/g, '&#96;');
64
79
  }
80
+ function sanitizeHeaderValue(str) {
81
+ if (typeof str !== 'string') return str;
82
+ return str.replace(/[\r\n\x00-\x1F\x7F]/g, '');
83
+ }
65
84
  function hasXSS(input) {
66
85
  if (typeof input !== 'string') return false;
67
- var xssPatterns = [/<\s*script.*?>/i, /<\s*\/\s*script\s*>/i, /<\s*img.*?on\w+\s*=/i, /<\s*\w+\s*on\w+\s*=.*?>/i, /javascript\s*:/i, /vbscript\s*:/i, /expression\s*\(/i, /eval\s*\(/i, /alert\s*\(/i, /document\.cookie/i, /document\.write\s*\(/i, /window\.location/i, /innerHTML/i];
86
+ var xssPatterns = [/<\s*script.*?>/i, /<\s*\/\s*script\s*>/i, /<\s*\w+\s+[^>]*?\bon\w+\s*=/i, /javascript\s*:/i, /vbscript\s*:/i, /expression\s*\(/i, /eval\s*\(/i, /alert\s*\(/i, /document\.cookie/i, /document\.write\s*\(/i, /window\.location/i, /innerHTML/i];
68
87
  return xssPatterns.some(function (pattern) {
69
88
  return pattern.test(input);
70
89
  });
package/esm/index.d.ts CHANGED
@@ -185,3 +185,34 @@ export class LanguageDetector implements i18next.Module {
185
185
  caches: LanguageDetectorCaches
186
186
  ): void;
187
187
  }
188
+
189
+
190
+ export interface HapiPlugin<TOptions = any> {
191
+ name: string;
192
+ version: string;
193
+ register: (
194
+ server: {
195
+ ext: (
196
+ event: string,
197
+ method: (request: any, h: any) => any
198
+ ) => void;
199
+ },
200
+ options: TOptions & HandleOptions & { i18next?: I18next }
201
+ ) => void;
202
+ }
203
+
204
+ export const hapiPlugin: HapiPlugin;
205
+
206
+ declare const middleware: {
207
+ plugin: typeof plugin;
208
+ hapiPlugin: typeof hapiPlugin;
209
+ koaPlugin: typeof koaPlugin;
210
+ freshPlugin: typeof freshPlugin;
211
+ handle: typeof handle;
212
+ getResourcesHandler: typeof getResourcesHandler;
213
+ missingKeyHandler: typeof missingKeyHandler;
214
+ addRoute: typeof addRoute;
215
+ LanguageDetector: typeof LanguageDetector;
216
+ };
217
+
218
+ export default middleware;
package/esm/index.js CHANGED
@@ -4,7 +4,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5
5
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
6
6
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7
- function _regeneratorRuntime() { "use strict"; _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
7
+ function _regenerator() { var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
8
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
8
9
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
9
10
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
10
11
  import * as utils from './utils.js';
@@ -75,7 +76,7 @@ export function handle(i18next) {
75
76
  res.locals.resolvedLanguage = i18n.resolvedLanguage;
76
77
  }
77
78
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
78
- options.setHeader(res, 'Content-Language', utils.escape(lng));
79
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng));
79
80
  }
80
81
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng);
81
82
  req.resolvedLanguage = i18n.resolvedLanguage;
@@ -89,7 +90,7 @@ export function handle(i18next) {
89
90
  }
90
91
  req.language = req.locale = req.lng = lng;
91
92
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
92
- options.setHeader(res, 'Content-Language', utils.escape(lng));
93
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng));
93
94
  }
94
95
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng);
95
96
  req.resolvedLanguage = i18n.resolvedLanguage;
@@ -130,20 +131,19 @@ export function plugin(instance, options, next) {
130
131
  export function koaPlugin(i18next, options) {
131
132
  var middleware = handle(i18next, options);
132
133
  return function () {
133
- var _koaMiddleware = _asyncToGenerator(_regeneratorRuntime().mark(function _callee(ctx, next) {
134
- return _regeneratorRuntime().wrap(function _callee$(_context) {
135
- while (1) switch (_context.prev = _context.next) {
134
+ var _koaMiddleware = _asyncToGenerator(_regenerator().m(function _callee(ctx, next) {
135
+ return _regenerator().w(function (_context) {
136
+ while (1) switch (_context.n) {
136
137
  case 0:
137
- _context.next = 2;
138
+ _context.n = 1;
138
139
  return new Promise(function (resolve) {
139
140
  return middleware(ctx, ctx, resolve);
140
141
  });
141
- case 2:
142
- _context.next = 4;
142
+ case 1:
143
+ _context.n = 2;
143
144
  return next();
144
- case 4:
145
- case "end":
146
- return _context.stop();
145
+ case 2:
146
+ return _context.a(2);
147
147
  }
148
148
  }, _callee);
149
149
  }));
@@ -155,10 +155,10 @@ export function koaPlugin(i18next, options) {
155
155
  }
156
156
  export function freshPlugin(i18next, options) {
157
157
  return function () {
158
- var _ref = _asyncToGenerator(_regeneratorRuntime().mark(function _callee2(ctx) {
158
+ var _ref = _asyncToGenerator(_regenerator().m(function _callee2(ctx) {
159
159
  var placeholder, resp;
160
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
161
- while (1) switch (_context2.prev = _context2.next) {
160
+ return _regenerator().w(function (_context2) {
161
+ while (1) switch (_context2.n) {
162
162
  case 0:
163
163
  handle(i18next, _objectSpread(_objectSpread({}, options), {}, {
164
164
  attachLocals: true
@@ -171,15 +171,12 @@ export function freshPlugin(i18next, options) {
171
171
  ctx.state.languages = ctx.req.languages;
172
172
  placeholder = ctx.state.res;
173
173
  delete ctx.state.res;
174
- _context2.next = 11;
174
+ _context2.n = 1;
175
175
  return ctx.next();
176
- case 11:
177
- resp = _context2.sent;
176
+ case 1:
177
+ resp = _context2.v;
178
178
  resp.headers.set('Content-Language', placeholder.headers.get('Content-Language'));
179
- return _context2.abrupt("return", resp);
180
- case 14:
181
- case "end":
182
- return _context2.stop();
179
+ return _context2.a(2, resp);
183
180
  }
184
181
  }, _callee2);
185
182
  }));
@@ -230,6 +227,8 @@ export function getResourcesHandler(i18next) {
230
227
  languages = options.getParams(req)[options.lngParam || 'lng'] ? options.getParams(req)[options.lngParam || 'lng'].split(' ') : [];
231
228
  namespaces = options.getParams(req)[options.nsParam || 'ns'] ? options.getParams(req)[options.nsParam || 'ns'].split(' ') : [];
232
229
  }
230
+ languages = languages.filter(utils.isSafeIdentifier);
231
+ namespaces = namespaces.filter(utils.isSafeIdentifier);
233
232
  namespaces.forEach(function (ns) {
234
233
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
235
234
  i18next.options.ns.push(ns);
@@ -262,22 +261,26 @@ export function missingKeyHandler(i18next) {
262
261
  return options.send(res, 'i18next-express-middleware:: no backend configured');
263
262
  }
264
263
  var body = options.getBody(req);
264
+ var saveMissingKeys = function saveMissingKeys(src) {
265
+ if (!src || _typeof(src) !== 'object') return;
266
+ for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
267
+ var m = _Object$keys[_i];
268
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue;
269
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
270
+ }
271
+ };
265
272
  if (typeof body === 'function') {
266
273
  var promise = body();
267
274
  if (promise && typeof promise.then === 'function') {
268
275
  return new Promise(function (resolve) {
269
276
  promise.then(function (b) {
270
- for (var m in b) {
271
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m]);
272
- }
277
+ saveMissingKeys(b);
273
278
  resolve(options.send(res, 'ok'));
274
279
  });
275
280
  });
276
281
  }
277
282
  }
278
- for (var m in body) {
279
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m]);
280
- }
283
+ saveMissingKeys(body);
281
284
  return options.send(res, 'ok');
282
285
  };
283
286
  }
@@ -78,6 +78,8 @@ export default {
78
78
  sameSite: options.cookieSameSite
79
79
  };
80
80
  if (options.cookieSecure) cookieOptions.secure = options.cookieSecure;
81
+ var sameSiteNormalised = typeof cookieOptions.sameSite === 'string' ? cookieOptions.sameSite.toLowerCase() : cookieOptions.sameSite;
82
+ if (sameSiteNormalised === 'none') cookieOptions.secure = true;
81
83
  var existingCookie = options.getHeader(res, 'set-cookie') || options.getHeader(res, 'Set-Cookie') || [];
82
84
  if (typeof existingCookie === 'string') existingCookie = [existingCookie];
83
85
  if (!Array.isArray(existingCookie)) existingCookie = [];
package/esm/utils.js CHANGED
@@ -1,3 +1,13 @@
1
+ export var UNSAFE_KEYS = ['__proto__', 'constructor', 'prototype'];
2
+ export function isSafeIdentifier(v) {
3
+ if (typeof v !== 'string') return false;
4
+ if (v.length === 0 || v.length > 128) return false;
5
+ if (UNSAFE_KEYS.indexOf(v) > -1) return false;
6
+ if (v.indexOf('..') > -1) return false;
7
+ if (v.indexOf('/') > -1 || v.indexOf('\\') > -1) return false;
8
+ if (/[\x00-\x1F\x7F]/.test(v)) return false;
9
+ return true;
10
+ }
1
11
  export function setPath(object, path, newValue) {
2
12
  var stack;
3
13
  if (typeof path !== 'string') stack = [].concat(path);
@@ -5,11 +15,13 @@ export function setPath(object, path, newValue) {
5
15
  while (stack.length > 1) {
6
16
  var _key = stack.shift();
7
17
  if (_key.indexOf('###') > -1) _key = _key.replace(/###/g, '.');
18
+ if (UNSAFE_KEYS.indexOf(_key) > -1) return;
8
19
  if (!object[_key]) object[_key] = {};
9
20
  object = object[_key];
10
21
  }
11
22
  var key = stack.shift();
12
23
  if (key.indexOf('###') > -1) key = key.replace(/###/g, '.');
24
+ if (UNSAFE_KEYS.indexOf(key) > -1) return;
13
25
  object[key] = newValue;
14
26
  }
15
27
  var arr = [];
@@ -51,9 +63,13 @@ export function removeLngFromUrl(url, lookupFromPathIndex) {
51
63
  export function escape(str) {
52
64
  return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\//g, '&#x2F;').replace(/\\/g, '&#x5C;').replace(/`/g, '&#96;');
53
65
  }
66
+ export function sanitizeHeaderValue(str) {
67
+ if (typeof str !== 'string') return str;
68
+ return str.replace(/[\r\n\x00-\x1F\x7F]/g, '');
69
+ }
54
70
  export function hasXSS(input) {
55
71
  if (typeof input !== 'string') return false;
56
- var xssPatterns = [/<\s*script.*?>/i, /<\s*\/\s*script\s*>/i, /<\s*img.*?on\w+\s*=/i, /<\s*\w+\s*on\w+\s*=.*?>/i, /javascript\s*:/i, /vbscript\s*:/i, /expression\s*\(/i, /eval\s*\(/i, /alert\s*\(/i, /document\.cookie/i, /document\.write\s*\(/i, /window\.location/i, /innerHTML/i];
72
+ var xssPatterns = [/<\s*script.*?>/i, /<\s*\/\s*script\s*>/i, /<\s*\w+\s+[^>]*?\bon\w+\s*=/i, /javascript\s*:/i, /vbscript\s*:/i, /expression\s*\(/i, /eval\s*\(/i, /alert\s*\(/i, /document\.cookie/i, /document\.write\s*\(/i, /window\.location/i, /innerHTML/i];
57
73
  return xssPatterns.some(function (pattern) {
58
74
  return pattern.test(input);
59
75
  });
package/index.d.ts CHANGED
@@ -185,3 +185,34 @@ export class LanguageDetector implements i18next.Module {
185
185
  caches: LanguageDetectorCaches
186
186
  ): void;
187
187
  }
188
+
189
+
190
+ export interface HapiPlugin<TOptions = any> {
191
+ name: string;
192
+ version: string;
193
+ register: (
194
+ server: {
195
+ ext: (
196
+ event: string,
197
+ method: (request: any, h: any) => any
198
+ ) => void;
199
+ },
200
+ options: TOptions & HandleOptions & { i18next?: I18next }
201
+ ) => void;
202
+ }
203
+
204
+ export const hapiPlugin: HapiPlugin;
205
+
206
+ declare const middleware: {
207
+ plugin: typeof plugin;
208
+ hapiPlugin: typeof hapiPlugin;
209
+ koaPlugin: typeof koaPlugin;
210
+ freshPlugin: typeof freshPlugin;
211
+ handle: typeof handle;
212
+ getResourcesHandler: typeof getResourcesHandler;
213
+ missingKeyHandler: typeof missingKeyHandler;
214
+ addRoute: typeof addRoute;
215
+ LanguageDetector: typeof LanguageDetector;
216
+ };
217
+
218
+ export default middleware;
package/lib/index.js CHANGED
@@ -69,7 +69,7 @@ export function handle (i18next, options = {}) {
69
69
  }
70
70
 
71
71
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
72
- options.setHeader(res, 'Content-Language', utils.escape(lng))
72
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng))
73
73
  }
74
74
 
75
75
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng)
@@ -88,7 +88,7 @@ export function handle (i18next, options = {}) {
88
88
  // set locale
89
89
  req.language = req.locale = req.lng = lng
90
90
  if (lng && options.getHeader(res, 'Content-Language') !== lng) {
91
- options.setHeader(res, 'Content-Language', utils.escape(lng))
91
+ options.setHeader(res, 'Content-Language', utils.sanitizeHeaderValue(lng))
92
92
  }
93
93
  req.languages = i18next.services.languageUtils.toResolveHierarchy(lng)
94
94
  req.resolvedLanguage = i18n.resolvedLanguage
@@ -243,6 +243,14 @@ export function getResourcesHandler (i18next, options = {}) {
243
243
  : []
244
244
  }
245
245
 
246
+ // Drop user-supplied values containing patterns that could trigger path
247
+ // traversal / SSRF / prototype pollution when forwarded to the backend
248
+ // connector. i18next itself permits arbitrary language codes, so we do
249
+ // not impose a BCP-47 shape — we only block known-dangerous patterns.
250
+ // See: https://www.i18next.com/how-to/faq#how-should-the-language-codes-be-formatted
251
+ languages = languages.filter(utils.isSafeIdentifier)
252
+ namespaces = namespaces.filter(utils.isSafeIdentifier)
253
+
246
254
  // extend ns
247
255
  namespaces.forEach(ns => {
248
256
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
@@ -290,23 +298,28 @@ export function missingKeyHandler (i18next, options = {}) {
290
298
 
291
299
  const body = options.getBody(req)
292
300
 
301
+ // iterate only over own, non-prototype-polluting keys
302
+ const saveMissingKeys = src => {
303
+ if (!src || typeof src !== 'object') return
304
+ for (const m of Object.keys(src)) {
305
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue
306
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m])
307
+ }
308
+ }
309
+
293
310
  if (typeof body === 'function') {
294
311
  const promise = body()
295
312
  if (promise && typeof promise.then === 'function') {
296
313
  return new Promise(resolve => {
297
314
  promise.then(b => {
298
- for (const m in b) {
299
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m])
300
- }
315
+ saveMissingKeys(b)
301
316
  resolve(options.send(res, 'ok'))
302
317
  })
303
318
  })
304
319
  }
305
320
  }
306
321
 
307
- for (const m in body) {
308
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m])
309
- }
322
+ saveMissingKeys(body)
310
323
 
311
324
  return options.send(res, 'ok')
312
325
  }
@@ -86,6 +86,13 @@ export default {
86
86
 
87
87
  if (options.cookieSecure) cookieOptions.secure = options.cookieSecure
88
88
 
89
+ // SameSite=None requires Secure — browsers reject the cookie otherwise.
90
+ // Force Secure in that case so misconfigured setups still function.
91
+ const sameSiteNormalised = typeof cookieOptions.sameSite === 'string'
92
+ ? cookieOptions.sameSite.toLowerCase()
93
+ : cookieOptions.sameSite
94
+ if (sameSiteNormalised === 'none') cookieOptions.secure = true
95
+
89
96
  let existingCookie = options.getHeader(res, 'set-cookie') || options.getHeader(res, 'Set-Cookie') || []
90
97
  if (typeof existingCookie === 'string') existingCookie = [existingCookie]
91
98
  if (!Array.isArray(existingCookie)) existingCookie = []
package/lib/utils.js CHANGED
@@ -1,3 +1,25 @@
1
+ export const UNSAFE_KEYS = ['__proto__', 'constructor', 'prototype']
2
+
3
+ // Returns true if `v` can be safely forwarded as a language code or namespace
4
+ // identifier to a backend connector. Denylist approach (i18next permits any
5
+ // language-code shape — https://www.i18next.com/how-to/faq#how-should-the-language-codes-be-formatted)
6
+ // that blocks the concrete attack patterns without restricting legitimate use:
7
+ // - not one of `__proto__` / `constructor` / `prototype` (prototype pollution)
8
+ // - no path separators `/` or `\` (path traversal / SSRF in fs/http backends)
9
+ // - no `..` sequence (relative path traversal)
10
+ // - no control characters (header injection downstream, log forging)
11
+ // - non-empty, length <= 128
12
+ export function isSafeIdentifier (v) {
13
+ if (typeof v !== 'string') return false
14
+ if (v.length === 0 || v.length > 128) return false
15
+ if (UNSAFE_KEYS.indexOf(v) > -1) return false
16
+ if (v.indexOf('..') > -1) return false
17
+ if (v.indexOf('/') > -1 || v.indexOf('\\') > -1) return false
18
+ // eslint-disable-next-line no-control-regex
19
+ if (/[\x00-\x1F\x7F]/.test(v)) return false
20
+ return true
21
+ }
22
+
1
23
  export function setPath (object, path, newValue) {
2
24
  let stack
3
25
  if (typeof path !== 'string') stack = [].concat(path)
@@ -6,12 +28,14 @@ export function setPath (object, path, newValue) {
6
28
  while (stack.length > 1) {
7
29
  let key = stack.shift()
8
30
  if (key.indexOf('###') > -1) key = key.replace(/###/g, '.')
31
+ if (UNSAFE_KEYS.indexOf(key) > -1) return // guard against prototype pollution
9
32
  if (!object[key]) object[key] = {}
10
33
  object = object[key]
11
34
  }
12
35
 
13
36
  let key = stack.shift()
14
37
  if (key.indexOf('###') > -1) key = key.replace(/###/g, '.')
38
+ if (UNSAFE_KEYS.indexOf(key) > -1) return // guard against prototype pollution
15
39
  object[key] = newValue
16
40
  }
17
41
 
@@ -70,6 +94,15 @@ export function escape (str) {
70
94
  .replace(/`/g, '&#96;'))
71
95
  }
72
96
 
97
+ // Strip control characters (CR, LF, NUL, other C0/C1) from a value before
98
+ // writing it into an HTTP header. Prevents HTTP response splitting on older
99
+ // Node.js, and unhandled ERR_INVALID_CHAR crashes on newer Node.js.
100
+ export function sanitizeHeaderValue (str) {
101
+ if (typeof str !== 'string') return str
102
+ // eslint-disable-next-line no-control-regex
103
+ return str.replace(/[\r\n\x00-\x1F\x7F]/g, '')
104
+ }
105
+
73
106
  export function hasXSS (input) {
74
107
  if (typeof input !== 'string') return false
75
108
 
@@ -77,8 +110,8 @@ export function hasXSS (input) {
77
110
  const xssPatterns = [
78
111
  /<\s*script.*?>/i,
79
112
  /<\s*\/\s*script\s*>/i,
80
- /<\s*img.*?on\w+\s*=/i,
81
- /<\s*\w+\s*on\w+\s*=.*?>/i,
113
+ // event handlers on any tag position (not just first attribute)
114
+ /<\s*\w+\s+[^>]*?\bon\w+\s*=/i,
82
115
  /javascript\s*:/i,
83
116
  /vbscript\s*:/i,
84
117
  /expression\s*\(/i,
package/licence CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2025 i18next
1
+ Copyright (c) 2020-present i18next
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "i18next-http-middleware",
3
- "version": "3.9.1",
3
+ "version": "3.9.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./cjs/index.js",
@@ -28,15 +28,15 @@
28
28
  },
29
29
  "module": "./esm/index.js",
30
30
  "devDependencies": {
31
- "@babel/cli": "7.25.9",
32
- "@babel/core": "7.26.0",
33
- "@babel/preset-env": "7.26.0",
34
- "@hapi/hapi": "^21.3.12",
35
- "@opentelemetry/api": "^1.9.0",
36
- "@preact/signals": "^2.2.1",
37
- "@types/express-serve-static-core": "^5.0.1",
38
- "@koa/router": "12.0.1",
39
- "koa": "2.16.1",
31
+ "@babel/cli": "7.28.6",
32
+ "@babel/core": "7.29.0",
33
+ "@babel/preset-env": "7.29.2",
34
+ "@hapi/hapi": "^21.4.8",
35
+ "@opentelemetry/api": "^1.9.1",
36
+ "@preact/signals": "^2.9.0",
37
+ "@types/express-serve-static-core": "^5.1.1",
38
+ "@koa/router": "15.4.0",
39
+ "koa": "3.2.0",
40
40
  "babel-plugin-add-module-exports": "1.0.4",
41
41
  "eslint": "8.53.0",
42
42
  "eslint-config-standard": "17.1.0",
@@ -46,14 +46,14 @@
46
46
  "eslint-plugin-require-path-exists": "1.1.9",
47
47
  "eslint-plugin-standard": "5.0.0",
48
48
  "expect.js": "0.3.1",
49
- "express": "4.21.1",
50
- "fastify": "5.3.2",
51
- "i18next": "25.5.2",
52
- "mocha": "10.8.2",
53
- "preact": "10.27.2",
54
- "preact-render-to-string": "6.6.3",
55
- "supertest": "7.0.0",
56
- "tsd": "0.31.2",
49
+ "express": "5.2.1",
50
+ "fastify": "5.8.5",
51
+ "i18next": "26.0.5",
52
+ "mocha": "11.7.5",
53
+ "preact": "10.29.1",
54
+ "preact-render-to-string": "6.6.7",
55
+ "supertest": "7.2.2",
56
+ "tsd": "0.33.0",
57
57
  "uglify-js": "3.19.3"
58
58
  },
59
59
  "description": "i18next-http-middleware is a middleware to be used with Node.js web frameworks like express or Fastify and also for Deno.",