@smpx/koa-request 0.2.7 → 0.4.0

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/Request.js CHANGED
@@ -10,6 +10,8 @@ const enableBasicAuth = require('./basicAuth');
10
10
  const enableStaticPaths = require('./staticPaths');
11
11
  const enableBotBanning = require('./botBanning');
12
12
 
13
+ const {setLogger, logError} = require('./logger');
14
+
13
15
  const uaParser = new UAParser();
14
16
 
15
17
  const ONE_HOUR = 3600 * 1000;
@@ -37,6 +39,7 @@ const COOKIEID_COOKIE = 'id';
37
39
  const COOKIE_PARAM_PREFIX = '_ck_';
38
40
  const USER_TOKEN_COOKIE = 'utok';
39
41
  const FLASH_COOKIE = 'flash';
42
+ const VIEWPORT_WIDTH_COOKIE = 'vw';
40
43
  // these cookies are httpOnly, should not be readable from js
41
44
  const SENSITIVE_COOKIES = [USER_TOKEN_COOKIE, COOKIEID_COOKIE, SESSIONID_COOKIE];
42
45
 
@@ -122,19 +125,25 @@ function getIntegerKey(key) {
122
125
  }
123
126
 
124
127
  function addQuery(url, query = {}) {
125
- const uri = new URL(url, 'http://localhost');
126
- if (typeof query === 'string') {
127
- query = new URLSearchParams(query);
128
- for (const [key, val] of query) {
129
- uri.searchParams.set(key, val);
128
+ try {
129
+ const uri = new URL(url, 'http://localhost');
130
+ if (typeof query === 'string') {
131
+ query = new URLSearchParams(query);
132
+ for (const [key, val] of query) {
133
+ uri.searchParams.set(key, val);
134
+ }
130
135
  }
131
- }
132
- else {
133
- for (const [key, val] of Object.entries(query)) {
134
- uri.searchParams.set(key, val);
136
+ else {
137
+ for (const [key, val] of Object.entries(query)) {
138
+ uri.searchParams.set(key, val);
139
+ }
135
140
  }
141
+ return `${uri.pathname}${uri.search}`;
142
+ }
143
+ catch (e) {
144
+ logError(e);
145
+ return url;
136
146
  }
137
- return `${uri.pathname}${uri.search}`;
138
147
  }
139
148
 
140
149
  const isProduction = (process.env.NODE_ENV === 'production');
@@ -756,9 +765,21 @@ class Request {
756
765
  return false;
757
766
  }
758
767
 
759
- if (!this._isMobileWeb) {
760
- const ua = this.parseUserAgent();
761
- this._isMobileWeb = (ua && ua.device && ua.device.type === 'mobile') || false;
768
+ if (this._isMobileWeb == null) {
769
+ const secHeader = this.ctx.headers['sec-ch-ua-mobile'];
770
+ if (secHeader) {
771
+ this._isMobileWeb = secHeader === '?1';
772
+ }
773
+ else {
774
+ const vwCookie = this.cookie(VIEWPORT_WIDTH_COOKIE);
775
+ if (vwCookie) {
776
+ this._isMobileWeb = Number(vwCookie) <= 750;
777
+ }
778
+ else {
779
+ const ua = this.parseUserAgent();
780
+ this._isMobileWeb = (ua && ua.device && ua.device.type === 'mobile') || false;
781
+ }
782
+ }
762
783
  }
763
784
  return this._isMobileWeb;
764
785
  }
@@ -767,6 +788,10 @@ class Request {
767
788
  return this.isMobileApp() || this.isMobileWeb();
768
789
  }
769
790
 
791
+ isAPI() {
792
+ return false;
793
+ }
794
+
770
795
  platform() {
771
796
  if (!this._platform) {
772
797
  if (this.isMobileApp()) {
@@ -1218,7 +1243,20 @@ class Request {
1218
1243
  };
1219
1244
  }
1220
1245
 
1221
- const refererUri = new URL(referer);
1246
+ let refererUri;
1247
+ try {
1248
+ refererUri = new URL(referer, 'http://localhost');
1249
+ }
1250
+ catch (e) {
1251
+ logError(e);
1252
+ return {
1253
+ name: '',
1254
+ source: 'direct',
1255
+ medium: 'direct',
1256
+ term: '',
1257
+ };
1258
+ }
1259
+
1222
1260
  let host = refererUri.hostname;
1223
1261
  const baseDomain = this.baseDomain();
1224
1262
 
@@ -1271,16 +1309,22 @@ class Request {
1271
1309
  * sets UTM cookies from a predefined url
1272
1310
  */
1273
1311
  setUTMCookieFromUrl(url) {
1274
- const uri = (url instanceof URL) ? url : new URL(url, 'http://localhost');
1275
- const params = uri.searchParams;
1276
- this.setUTMCookieFromQuery({
1277
- utm_source: params.get('utm_source'),
1278
- utm_medium: params.get('utm_medium'),
1279
- utm_campaign: params.get('utm_campaign'),
1280
- utm_term: params.get('utm_term'),
1281
- utm_content: params.get('utm_content'),
1282
- gclid: params.get('gclid'),
1283
- });
1312
+ try {
1313
+ const uri = (url instanceof URL) ? url : new URL(url, 'http://localhost');
1314
+ const params = uri.searchParams;
1315
+ this.setUTMCookieFromQuery({
1316
+ utm_source: params.get('utm_source'),
1317
+ utm_medium: params.get('utm_medium'),
1318
+ utm_campaign: params.get('utm_campaign'),
1319
+ utm_term: params.get('utm_term'),
1320
+ utm_content: params.get('utm_content'),
1321
+ gclid: params.get('gclid'),
1322
+ });
1323
+ }
1324
+ catch (e) {
1325
+ logError(e);
1326
+ // ignore error
1327
+ }
1284
1328
  }
1285
1329
 
1286
1330
  /**
@@ -1337,19 +1381,25 @@ class Request {
1337
1381
  }
1338
1382
 
1339
1383
  setAffidCookieFromUrl(url) {
1340
- const uri = (url instanceof URL) ? url : new URL(url, 'http://localhost');
1341
- const params = uri.searchParams;
1342
- const affid = params.get(AFFID_PARAM);
1343
- if (!affid) return;
1344
- const subaffid = params.get(SUBAFFID_PARAM);
1345
-
1346
- this.cookie(
1347
- AFFID_COOKIE,
1348
- joinCookieParts([affid, subaffid]), {
1349
- maxAge: AFFID_COOKIE_DURATION,
1350
- domain: '*',
1351
- },
1352
- );
1384
+ try {
1385
+ const uri = (url instanceof URL) ? url : new URL(url, 'http://localhost');
1386
+ const params = uri.searchParams;
1387
+ const affid = params.get(AFFID_PARAM);
1388
+ if (!affid) return;
1389
+ const subaffid = params.get(SUBAFFID_PARAM);
1390
+
1391
+ this.cookie(
1392
+ AFFID_COOKIE,
1393
+ joinCookieParts([affid, subaffid]), {
1394
+ maxAge: AFFID_COOKIE_DURATION,
1395
+ domain: '*',
1396
+ },
1397
+ );
1398
+ }
1399
+ catch (e) {
1400
+ logError(e);
1401
+ // ignore error
1402
+ }
1353
1403
  }
1354
1404
 
1355
1405
  handlePlatformModification() {
@@ -1479,7 +1529,7 @@ class Request {
1479
1529
  }
1480
1530
  catch (e) {
1481
1531
  this._flash = '';
1482
- console.error('Error parsing flash message', e);
1532
+ logError('Error parsing flash message', e);
1483
1533
  }
1484
1534
 
1485
1535
  this.cookie(FLASH_COOKIE, null);
@@ -1561,4 +1611,5 @@ class Request {
1561
1611
  }
1562
1612
  }
1563
1613
 
1614
+ Request.setLogger = setLogger;
1564
1615
  module.exports = Request;
package/basicAuth.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const auth = require('koa-basic-auth');
2
2
 
3
- module.exports = function enableBasicAuth(app, options = {}) {
3
+ module.exports = function enableBasicAuth(app, options) {
4
4
  if (!options || options.enabled === false) return;
5
5
 
6
6
  app.use(async (ctx, next) => {
package/botBanning.js CHANGED
@@ -26,7 +26,7 @@ function banned(ctx, email) {
26
26
  ctx.body = `<pre>Our system has detected unusual traffic from your ip ${ip}. Hence your ip has been banned temporarily.\n${emailStr}</pre>`;
27
27
  }
28
28
 
29
- module.exports = function enableBotBanning(app, options = {}) {
29
+ module.exports = function enableBotBanning(app, options) {
30
30
  if (!options || options.enabled === false) return;
31
31
 
32
32
  let userAgents = [];
package/logger.js ADDED
@@ -0,0 +1,22 @@
1
+ let globalLogger;
2
+
3
+ /**
4
+ * set logger
5
+ */
6
+ function setLogger(logger) {
7
+ globalLogger = logger;
8
+ }
9
+
10
+ function logError(...args) {
11
+ if (globalLogger !== undefined) {
12
+ if (globalLogger) globalLogger.error(...args);
13
+ }
14
+ else {
15
+ console.error(...args);
16
+ }
17
+ }
18
+
19
+ module.exports = {
20
+ setLogger,
21
+ logError,
22
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smpx/koa-request",
3
- "version": "0.2.7",
3
+ "version": "0.4.0",
4
4
  "description": "Handle basic tasks for koajs",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -30,12 +30,12 @@
30
30
  },
31
31
  "homepage": "https://github.com/smartprix/koa-request#readme",
32
32
  "dependencies": {
33
- "ip": "^1.1.5",
33
+ "ip": "^1.1.8",
34
34
  "koa-basic-auth": "^4.0.0",
35
- "koa-body": "^4.2.0",
35
+ "koa-body": "^5.0.0",
36
36
  "koa-send": "^5.0.1",
37
- "koa2-ratelimit": "^0.9.1",
38
- "maxmind": "^4.3.3",
37
+ "koa2-ratelimit": "^1.1.1",
38
+ "maxmind": "^4.3.6",
39
39
  "tar": "^6.1.11",
40
40
  "ua-parser-js": "^1.0.2"
41
41
  },
package/rateLimit.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const {RateLimit} = require('koa2-ratelimit');
2
2
 
3
- module.exports = function enableRateLimit(app, options = {}) {
3
+ module.exports = function enableRateLimit(app, options) {
4
4
  if (!options || options.enabled === false) return;
5
5
 
6
6
  const skip = options.skip;
package/staticPaths.js CHANGED
@@ -13,16 +13,15 @@ function getMiddleware(options) {
13
13
  }
14
14
 
15
15
  return async (ctx, next) => {
16
+ if (options.disabled) {
17
+ await next();
18
+ return;
19
+ }
20
+
16
21
  if (options.path === '/') {
17
22
  // root requires special handling to check if extension denotes a static path
18
- const matches = ctx.path.match(/^\/(.*)\.(jpg|jpeg|gif|png|ico|css|js|json|ttf|otf|eot|woff|svg|svgz|xml|html|txt|ogg|ogv|mp4|rss|atom|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$/);
19
- if (!matches) {
20
- await next();
21
- return;
22
- }
23
-
24
- // skip the current path
25
- if (options.skip && options.skip(ctx)) {
23
+ const isStatic = /^\/(.*)\.(jpg|jpeg|gif|png|webp|avif|jxl|ico|css|js|mjs|json|ttf|otf|eot|woff|woff2|svg|svgz|xml|html|txt|ogg|ogv|mp4|av1|webm|rss|atom|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$/.test(ctx.path);
24
+ if (!isStatic) {
26
25
  await next();
27
26
  return;
28
27
  }
@@ -34,6 +33,12 @@ function getMiddleware(options) {
34
33
  return;
35
34
  }
36
35
 
36
+ // skip the current path
37
+ if (options.skip && options.skip(ctx)) {
38
+ await next();
39
+ return;
40
+ }
41
+
37
42
  // only GET or GET like methods are allowed
38
43
  if (!['get', 'head', 'options'].includes(ctx.method.toLowerCase())) {
39
44
  ctx.body = 'Method Not Allowed';
@@ -43,7 +48,7 @@ function getMiddleware(options) {
43
48
 
44
49
  if (options.immutable) {
45
50
  // return a 304 not modified response, as immutables can't be modified
46
- if (ctx.headers['if-modified-since']) {
51
+ if (ctx.headers['if-modified-since'] && !ctx.response.get('Cache-Control')) {
47
52
  ctx.status = 304;
48
53
  return;
49
54
  }