i18next-http-middleware 3.9.2 → 3.9.4

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.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) {
177
- var placeholder, resp;
178
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
179
- while (1) switch (_context2.prev = _context2.next) {
175
+ var _ref = _asyncToGenerator(_regenerator().m(function _callee2(ctx) {
176
+ var placeholder, resp, contentLanguage, setCookie;
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,19 @@ 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;
196
- 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();
193
+ case 1:
194
+ resp = _context2.v;
195
+ contentLanguage = placeholder.headers.get('Content-Language');
196
+ if (contentLanguage) {
197
+ resp.headers.set('Content-Language', contentLanguage);
198
+ }
199
+ setCookie = placeholder.headers.get('Set-Cookie');
200
+ if (setCookie) {
201
+ resp.headers.set('Set-Cookie', setCookie);
202
+ }
203
+ return _context2.a(2, resp);
201
204
  }
202
205
  }, _callee2);
203
206
  }));
@@ -248,6 +251,8 @@ function getResourcesHandler(i18next) {
248
251
  languages = options.getParams(req)[options.lngParam || 'lng'] ? options.getParams(req)[options.lngParam || 'lng'].split(' ') : [];
249
252
  namespaces = options.getParams(req)[options.nsParam || 'ns'] ? options.getParams(req)[options.nsParam || 'ns'].split(' ') : [];
250
253
  }
254
+ languages = languages.filter(utils.isSafeIdentifier);
255
+ namespaces = namespaces.filter(utils.isSafeIdentifier);
251
256
  namespaces.forEach(function (ns) {
252
257
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
253
258
  i18next.options.ns.push(ns);
@@ -280,22 +285,26 @@ function missingKeyHandler(i18next) {
280
285
  return options.send(res, 'i18next-express-middleware:: no backend configured');
281
286
  }
282
287
  var body = options.getBody(req);
288
+ var saveMissingKeys = function saveMissingKeys(src) {
289
+ if (!src || _typeof(src) !== 'object') return;
290
+ for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
291
+ var m = _Object$keys[_i];
292
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue;
293
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
294
+ }
295
+ };
283
296
  if (typeof body === 'function') {
284
297
  var promise = body();
285
298
  if (promise && typeof promise.then === 'function') {
286
299
  return new Promise(function (resolve) {
287
300
  promise.then(function (b) {
288
- for (var m in b) {
289
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m]);
290
- }
301
+ saveMissingKeys(b);
291
302
  resolve(options.send(res, 'ok'));
292
303
  });
293
304
  });
294
305
  }
295
306
  }
296
- for (var m in body) {
297
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m]);
298
- }
307
+ saveMissingKeys(body);
299
308
  return options.send(res, 'ok');
300
309
  };
301
310
  }
@@ -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.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) {
159
- var placeholder, resp;
160
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
161
- while (1) switch (_context2.prev = _context2.next) {
158
+ var _ref = _asyncToGenerator(_regenerator().m(function _callee2(ctx) {
159
+ var placeholder, resp, contentLanguage, setCookie;
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,19 @@ 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;
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();
176
+ case 1:
177
+ resp = _context2.v;
178
+ contentLanguage = placeholder.headers.get('Content-Language');
179
+ if (contentLanguage) {
180
+ resp.headers.set('Content-Language', contentLanguage);
181
+ }
182
+ setCookie = placeholder.headers.get('Set-Cookie');
183
+ if (setCookie) {
184
+ resp.headers.set('Set-Cookie', setCookie);
185
+ }
186
+ return _context2.a(2, resp);
183
187
  }
184
188
  }, _callee2);
185
189
  }));
@@ -230,6 +234,8 @@ export function getResourcesHandler(i18next) {
230
234
  languages = options.getParams(req)[options.lngParam || 'lng'] ? options.getParams(req)[options.lngParam || 'lng'].split(' ') : [];
231
235
  namespaces = options.getParams(req)[options.nsParam || 'ns'] ? options.getParams(req)[options.nsParam || 'ns'].split(' ') : [];
232
236
  }
237
+ languages = languages.filter(utils.isSafeIdentifier);
238
+ namespaces = namespaces.filter(utils.isSafeIdentifier);
233
239
  namespaces.forEach(function (ns) {
234
240
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
235
241
  i18next.options.ns.push(ns);
@@ -262,22 +268,26 @@ export function missingKeyHandler(i18next) {
262
268
  return options.send(res, 'i18next-express-middleware:: no backend configured');
263
269
  }
264
270
  var body = options.getBody(req);
271
+ var saveMissingKeys = function saveMissingKeys(src) {
272
+ if (!src || _typeof(src) !== 'object') return;
273
+ for (var _i = 0, _Object$keys = Object.keys(src); _i < _Object$keys.length; _i++) {
274
+ var m = _Object$keys[_i];
275
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue;
276
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m]);
277
+ }
278
+ };
265
279
  if (typeof body === 'function') {
266
280
  var promise = body();
267
281
  if (promise && typeof promise.then === 'function') {
268
282
  return new Promise(function (resolve) {
269
283
  promise.then(function (b) {
270
- for (var m in b) {
271
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m]);
272
- }
284
+ saveMissingKeys(b);
273
285
  resolve(options.send(res, 'ok'));
274
286
  });
275
287
  });
276
288
  }
277
289
  }
278
- for (var m in body) {
279
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m]);
280
- }
290
+ saveMissingKeys(body);
281
291
  return options.send(res, 'ok');
282
292
  };
283
293
  }
@@ -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/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
@@ -162,7 +162,17 @@ export function freshPlugin (i18next, options) {
162
162
  const placeholder = ctx.state.res
163
163
  delete ctx.state.res
164
164
  const resp = await ctx.next()
165
- resp.headers.set('Content-Language', placeholder.headers.get('Content-Language'))
165
+
166
+ const contentLanguage = placeholder.headers.get('Content-Language')
167
+ if (contentLanguage) {
168
+ resp.headers.set('Content-Language', contentLanguage)
169
+ }
170
+
171
+ const setCookie = placeholder.headers.get('Set-Cookie')
172
+ if (setCookie) {
173
+ resp.headers.set('Set-Cookie', setCookie)
174
+ }
175
+
166
176
  return resp
167
177
  }
168
178
  }
@@ -243,6 +253,14 @@ export function getResourcesHandler (i18next, options = {}) {
243
253
  : []
244
254
  }
245
255
 
256
+ // Drop user-supplied values containing patterns that could trigger path
257
+ // traversal / SSRF / prototype pollution when forwarded to the backend
258
+ // connector. i18next itself permits arbitrary language codes, so we do
259
+ // not impose a BCP-47 shape — we only block known-dangerous patterns.
260
+ // See: https://www.i18next.com/how-to/faq#how-should-the-language-codes-be-formatted
261
+ languages = languages.filter(utils.isSafeIdentifier)
262
+ namespaces = namespaces.filter(utils.isSafeIdentifier)
263
+
246
264
  // extend ns
247
265
  namespaces.forEach(ns => {
248
266
  if (i18next.options.ns && i18next.options.ns.indexOf(ns) < 0) {
@@ -290,23 +308,28 @@ export function missingKeyHandler (i18next, options = {}) {
290
308
 
291
309
  const body = options.getBody(req)
292
310
 
311
+ // iterate only over own, non-prototype-polluting keys
312
+ const saveMissingKeys = src => {
313
+ if (!src || typeof src !== 'object') return
314
+ for (const m of Object.keys(src)) {
315
+ if (utils.UNSAFE_KEYS.indexOf(m) > -1) continue
316
+ i18next.services.backendConnector.saveMissing([lng], ns, m, src[m])
317
+ }
318
+ }
319
+
293
320
  if (typeof body === 'function') {
294
321
  const promise = body()
295
322
  if (promise && typeof promise.then === 'function') {
296
323
  return new Promise(resolve => {
297
324
  promise.then(b => {
298
- for (const m in b) {
299
- i18next.services.backendConnector.saveMissing([lng], ns, m, b[m])
300
- }
325
+ saveMissingKeys(b)
301
326
  resolve(options.send(res, 'ok'))
302
327
  })
303
328
  })
304
329
  }
305
330
  }
306
331
 
307
- for (const m in body) {
308
- i18next.services.backendConnector.saveMissing([lng], ns, m, body[m])
309
- }
332
+ saveMissingKeys(body)
310
333
 
311
334
  return options.send(res, 'ok')
312
335
  }
@@ -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.2",
3
+ "version": "3.9.4",
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.",