profoundjs-swagger-stats 1.1.3 → 2.0.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dashboards/prometheus/swagger-stats dashboard v3.json +1269 -0
  3. package/examples/authtest/authtest.js +5 -10
  4. package/examples/fastify/fasifytest.js +24 -5
  5. package/examples/hapijstest/hapijstest.js +17 -2
  6. package/examples/restify/restifytest.js +16 -1
  7. package/examples/spectest/spectest.js +7 -9
  8. package/examples/testapp/petstore.json +1699 -0
  9. package/examples/testapp/testapp.js +6 -62
  10. package/lib/sws-api-swagger.yaml +1 -1
  11. package/lib/swsAPIStats.js +6 -1
  12. package/lib/swsAuth.js +140 -0
  13. package/lib/swsElasticEmitter.js +103 -45
  14. package/lib/swsHapi.js +29 -34
  15. package/lib/swsInterface.js +40 -189
  16. package/lib/swsProcessor.js +1 -1
  17. package/lib/swsReqResStats.js +1 -1
  18. package/lib/swsUtil.js +7 -21
  19. package/lib/swssettings.js +8 -2
  20. package/package.json +90 -91
  21. package/schema/elasticsearch/api_index_template.json +1 -1
  22. package/schema/elasticsearch/api_index_template_7x.json +185 -0
  23. package/scripts/elasticsearch/elastic7/docker-compose.yml +6 -17
  24. package/scripts/elasticsearch/elastic8/docker-compose.yml +34 -0
  25. package/ux/css/app.dc22c4da.css +7 -0
  26. package/ux/css/chunk-vendors.a6da6d7a.css +10 -0
  27. package/ux/fonts/KFOkCnqEu92Fr1MmgVxIIzQ.4aa2e698.woff +0 -0
  28. package/ux/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.40bcb2b8.woff +0 -0
  29. package/ux/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.ea60988b.woff +0 -0
  30. package/ux/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.0774a8b7.woff +0 -0
  31. package/ux/fonts/KFOlCnqEu92Fr1MmYUtfBBc-.bcb7c7e2.woff +0 -0
  32. package/ux/fonts/KFOmCnqEu92Fr1Mu4mxM.d3907d0c.woff +0 -0
  33. package/ux/fonts/fa-brands-400.1a575a41.woff +0 -0
  34. package/ux/fonts/fa-brands-400.ed311c7a.woff2 +0 -0
  35. package/ux/fonts/fa-regular-400.b91d376b.woff2 +0 -0
  36. package/ux/fonts/fa-regular-400.d1d7e3b4.woff +0 -0
  37. package/ux/fonts/fa-solid-900.d745348d.woff +0 -0
  38. package/ux/fonts/fa-solid-900.d824df7e.woff2 +0 -0
  39. package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.3e1afe59.woff +0 -0
  40. package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.a4160421.woff2 +0 -0
  41. package/ux/index.html +1 -1
  42. package/ux/js/app.d095d0d6.js +1 -0
  43. package/ux/js/chunk-2d0b90b4.afe783bc.js +8 -0
  44. package/ux/js/chunk-2d0daf1e.a05fda31.js +11 -0
  45. package/ux/js/chunk-461883cd.a2aa4876.js +82 -0
  46. package/ux/js/chunk-vendors.4f167dc9.js +39 -0
  47. package/ux/logo.png +0 -0
  48. package/.editorconfig +0 -21
  49. package/.travis.yml +0 -23
  50. package/dashboards/prometheus/swagger-stats dashboard.json +0 -1118
  51. package/dist/css/sws.min.css +0 -18
  52. package/dist/fonts/FontAwesome.otf +0 -0
  53. package/dist/fonts/fontawesome-webfont.eot +0 -0
  54. package/dist/fonts/fontawesome-webfont.svg +0 -2671
  55. package/dist/fonts/fontawesome-webfont.ttf +0 -0
  56. package/dist/fonts/fontawesome-webfont.woff +0 -0
  57. package/dist/fonts/fontawesome-webfont.woff2 +0 -0
  58. package/dist/fonts/glyphicons-halflings-regular.eot +0 -0
  59. package/dist/fonts/glyphicons-halflings-regular.svg +0 -288
  60. package/dist/fonts/glyphicons-halflings-regular.ttf +0 -0
  61. package/dist/fonts/glyphicons-halflings-regular.woff +0 -0
  62. package/dist/fonts/glyphicons-halflings-regular.woff2 +0 -0
  63. package/dist/images/favicon.png +0 -0
  64. package/dist/js/sws.min.js +0 -1
  65. package/gulpfile.js +0 -103
  66. package/karma.conf.js +0 -153
  67. package/ux/css/app.71245b0e.css +0 -7
  68. package/ux/css/chunk-vendors.809c52d1.css +0 -10
  69. package/ux/fonts/KFOkCnqEu92Fr1MmgVxIIzQ.5cb7edfc.woff +0 -0
  70. package/ux/fonts/KFOlCnqEu92Fr1MmEU9fBBc-.87284894.woff +0 -0
  71. package/ux/fonts/KFOlCnqEu92Fr1MmSU5fBBc-.b00849e0.woff +0 -0
  72. package/ux/fonts/KFOlCnqEu92Fr1MmWUlfBBc-.adcde98f.woff +0 -0
  73. package/ux/fonts/KFOlCnqEu92Fr1MmYUtfBBc-.bb1e4dc6.woff +0 -0
  74. package/ux/fonts/KFOmCnqEu92Fr1Mu4mxM.60fa3c06.woff +0 -0
  75. package/ux/fonts/fa-brands-400.c5e0f14f.woff +0 -0
  76. package/ux/fonts/fa-brands-400.cccc9d29.woff2 +0 -0
  77. package/ux/fonts/fa-regular-400.c4f508e7.woff +0 -0
  78. package/ux/fonts/fa-regular-400.f5f2566b.woff2 +0 -0
  79. package/ux/fonts/fa-solid-900.333bae20.woff +0 -0
  80. package/ux/fonts/fa-solid-900.44d537ab.woff2 +0 -0
  81. package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNa.29b882f0.woff +0 -0
  82. package/ux/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.0509ab09.woff2 +0 -0
  83. package/ux/js/app.0159ef6a.js +0 -1
  84. package/ux/js/chunk-2d0b90b4.92f1ea49.js +0 -8
  85. package/ux/js/chunk-461883cd.442efb25.js +0 -76
  86. package/ux/js/chunk-vendors.31d3ce30.js +0 -33
  87. /package/ux/js/{chunk-2d0de2f2.553bf976.js → chunk-2d0de2f2.2848649c.js} +0 -0
@@ -1,5 +1,3 @@
1
- 'use strict';
2
-
3
1
  var http = require('http');
4
2
  var path = require('path');
5
3
  var debug = require('debug')('sws:testapp');
@@ -10,11 +8,8 @@ var server = null;
10
8
  // Express and middlewares
11
9
  var express = require('express');
12
10
  var expressBodyParser = require('body-parser');
13
- var expressFavicon = require('serve-favicon');
14
- var expressStatic = require('serve-static');
15
11
 
16
- var swaggerJSDoc = require('swagger-jsdoc');
17
- var swaggerParser = require('swagger-parser');
12
+ const swaggerParser = require('swagger-parser');
18
13
 
19
14
  var swStats = require('../../lib'); // require('swagger-stats');
20
15
 
@@ -22,11 +17,6 @@ var swStats = require('../../lib'); // require('swagger-stats');
22
17
  var API = require('./api');
23
18
 
24
19
  var app = module.exports = express();
25
- app.use(expressFavicon(path.join(__dirname, '../../ui/favicon.png')));
26
- app.use('/ui',expressStatic(path.join(__dirname, '../../ui')));
27
- app.use('/ui/dist',expressStatic(path.join(__dirname, '../../dist')));
28
- app.use('/node_modules',expressStatic(path.join(__dirname, '../../node_modules')));
29
- app.use('/node_modules',expressStatic(path.join(__dirname, '../../node_modules')));
30
20
  app.use(expressBodyParser.json()); // for parsing application/json
31
21
  app.use(expressBodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
32
22
 
@@ -37,7 +27,7 @@ app.set('port', process.env.PORT || 3040);
37
27
  app.disable('etag');
38
28
 
39
29
  app.get('/', function(req,res) {
40
- res.redirect('/ui');
30
+ res.redirect('/swagger-stats/');
41
31
  });
42
32
 
43
33
  app.get('/apidoc.json', function(req,res){
@@ -50,66 +40,20 @@ if( process.env.SWS_TEST_TIMEBUCKET ){
50
40
  tlBucket = parseInt(process.env.SWS_TEST_TIMEBUCKET);
51
41
  }
52
42
 
53
- // SWAGGER-JSDOC Initialization //
54
- var apifile = path.join(__dirname,'api.js');
55
- debug('initializing swagger spec from api file %s',apifile);
56
- var swOptions = {
57
- swaggerDefinition: {
58
- "info": {
59
- "description": "This is a Petstore API implementation for swagger-stats sample app",
60
- "version": "1.0.0",
61
- "title": "Swagger-Stats Petstore ",
62
- "contact": {
63
- "email": "sv2@slanatech.com"
64
- },
65
- "license": {
66
- "name": "MIT"
67
- }
68
- },
69
- "host": "localhost",
70
- "basePath": "/api/v1",
71
- "tags": [
72
- {
73
- "name": "pet",
74
- "description": "Everything about your Pets",
75
- "externalDocs": {
76
- "description": "Find out more",
77
- "url": "http://swaggerstats.io"
78
- }
79
- },
80
- {
81
- "name": "store",
82
- "description": "Access to Petstore orders"
83
- },
84
- {
85
- "name": "user",
86
- "description": "Operations about user",
87
- "externalDocs": {
88
- "description": "Find out more about our store",
89
- "url": "http://swaggerstats.io"
90
- }
91
- }
92
- ],
93
- "schemes": ["http"]
94
- },
95
- apis: [apifile] // Path to the API files with swagger docs in comments
96
- };
97
-
98
- // Initialize swagger-jsdoc -> returns validated swagger spec in json format
99
- var swaggerSpec = swaggerJSDoc(swOptions);
43
+ const swaggerSpec = require('./petstore.json');
100
44
 
101
45
  // Testing validation of 3rd-party API spec
102
- var parser = new swaggerParser();
46
+ const parser = new swaggerParser();
103
47
 
104
48
  parser.validate(swaggerSpec,function(err, api) {
105
49
  if (!err) {
106
50
  debug('Success validating swagger file!');
107
- swaggerSpec = api;
51
+ //swaggerSpec = api;
108
52
 
109
53
  // Enable swagger-stats middleware
110
54
  app.use(swStats.getMiddleware({
111
55
  name: 'swagger-stats-testapp',
112
- version: '0.95.17',
56
+ version: '0.99.7',
113
57
  timelineBucketDuration: tlBucket,
114
58
  uriPath: '/swagger-stats',
115
59
  swaggerSpec:swaggerSpec,
@@ -1,6 +1,6 @@
1
1
  swagger: '2.0'
2
2
  info:
3
- version: 0.95.17
3
+ version: 0.99.7
4
4
  title: swagger-stats API
5
5
  description: |
6
6
  ### Telemetry for your APIs
@@ -185,6 +185,7 @@ swsAPIStats.prototype.addPathSpecs = function (pathSpecs) {
185
185
  if( fullExpressPath.indexOf('{') !== -1 ) {
186
186
  fullExpressPath = fullExpressPath.replace(/\{/g, ':');
187
187
  fullExpressPath = fullExpressPath.replace(/\}/g, '');
188
+ fullExpressPath = fullExpressPath.replace(/\?(\w+=)/g, '\\?$1');
188
189
  re = pathToRegexp(fullExpressPath, keys);
189
190
  }
190
191
 
@@ -332,6 +333,10 @@ swsAPIStats.prototype.extractPathParams = function (matchResult,keys) {
332
333
  swsAPIStats.prototype.matchRequest = function (req) {
333
334
 
334
335
  var url = req.sws.originalUrl;
336
+ // Handle "/pets" and "/pets/" the same way - #105
337
+ if( url.endsWith('/') ) {
338
+ url = url.slice(0,-1);
339
+ }
335
340
 
336
341
  req.sws.match = false; // No match by default
337
342
 
@@ -351,7 +356,7 @@ swsAPIStats.prototype.matchRequest = function (req) {
351
356
  matchEntry = this.apiMatchIndex[url];
352
357
  apiPath = url;
353
358
  debug('SWS:MATCH: %s exact match', url);
354
- }else{
359
+ } else {
355
360
  // if not, search by regex matching
356
361
  for(var swPath in this.apiMatchIndex) {
357
362
  if( this.apiMatchIndex[swPath].re !== null) {
package/lib/swsAuth.js ADDED
@@ -0,0 +1,140 @@
1
+ const swsSettings = require('./swssettings');
2
+ const debug = require('debug')('sws:auth');
3
+ const basicAuth = require("basic-auth");
4
+ const Cookies = require('cookies');
5
+ const { v1: uuidv1 } = require('uuid');
6
+
7
+ /* Authentication */
8
+ class SwsAuth {
9
+
10
+ constructor() {
11
+ this.sessionIDs = {};
12
+ this.expireIntervalId = null;
13
+ }
14
+
15
+ storeSessionID(sid){
16
+ // PJS - Create sid value if not passed
17
+ sid = sid || uuidv1();
18
+
19
+ let tsSec = Date.now() + swsSettings.sessionMaxAge*1000;
20
+ this.sessionIDs[sid] = tsSec;
21
+ //debug('Session ID updated: %s=%d', sid,tssec);
22
+ if( !this.expireIntervalId ){
23
+ this.expireIntervalId = setInterval(() => {this.expireSessionIDs();},500);
24
+ }
25
+
26
+ // PJS - Send back sid value
27
+ return sid;
28
+ }
29
+
30
+ removeSessionID(sid){
31
+ delete this.sessionIDs[sid];
32
+ }
33
+
34
+ // If authentication is enabled, executed periodically and expires old session IDs
35
+ expireSessionIDs(){
36
+ let tssec = Date.now();
37
+ let expired = [];
38
+ for(let sid in this.sessionIDs){
39
+ if(this.sessionIDs[sid] < (tssec + 500)){
40
+ expired.push(sid);
41
+ }
42
+ }
43
+ for(let i=0;i<expired.length;i++){
44
+ delete this.sessionIDs[expired[i]];
45
+ debug('Session ID expired: %s', expired[i]);
46
+ }
47
+ }
48
+
49
+ async processAuth(req,res) {
50
+
51
+ if( !swsSettings.authentication ){
52
+ return true;
53
+ }
54
+
55
+ if( swsSettings.customAuth ){
56
+ // return swsSettings.customAuth(req);
57
+ // PJS Custom
58
+ return swsSettings.customAuth(req, res);
59
+ }
60
+
61
+ let cookies = new Cookies( req, res );
62
+
63
+ // Check session cookie
64
+ let sessionIdCookie = cookies.get('sws-session-id');
65
+ if( (sessionIdCookie !== undefined) && (sessionIdCookie !== null) ){
66
+
67
+ if( sessionIdCookie in this.sessionIDs ){
68
+ // renew it
69
+ //sessionIDs[sessionIdCookie] = Date.now();
70
+ this.storeSessionID(sessionIdCookie);
71
+ cookies.set('sws-session-id',sessionIdCookie,{path:swsSettings.basePath+swsSettings.uriPath,maxAge:swsSettings.sessionMaxAge*1000});
72
+ // Ok
73
+ req['sws-auth'] = true;
74
+ return true;
75
+ }
76
+ }
77
+
78
+ let authInfo = basicAuth(req);
79
+
80
+ let authenticated = false;
81
+ let msg = 'Authentication required';
82
+
83
+ if( (authInfo !== undefined) && (authInfo!==null) && ('name' in authInfo) && ('pass' in authInfo)){
84
+ if(typeof swsSettings.onAuthenticate === 'function'){
85
+
86
+ let onAuthResult = null;
87
+ try{
88
+ onAuthResult = await swsSettings.onAuthenticate(req, authInfo.name, authInfo.pass);
89
+ }catch (e){
90
+ msg = `Authentication error: ${e.message}`;
91
+ res.statusCode = 403;
92
+ res.end(msg);
93
+ return false;
94
+ }
95
+ if( onAuthResult ){
96
+ authenticated = true;
97
+ // Session is only for stats requests
98
+ if(req.url.startsWith(swsSettings.pathStats)){
99
+ // Generate session id
100
+ let sessid = uuidv1();
101
+ this.storeSessionID(sessid);
102
+ // Set session cookie with expiration in 15 min
103
+ cookies.set('sws-session-id',sessid,{path:swsSettings.basePath+swsSettings.uriPath,maxAge:swsSettings.sessionMaxAge*1000});
104
+ }
105
+ req['sws-auth'] = true;
106
+ return true;
107
+ } else {
108
+ res.statusCode = 403;
109
+ res.end(msg);
110
+ return false;
111
+ }
112
+ }else{
113
+ res.statusCode = 403;
114
+ res.end(msg);
115
+ return false;
116
+ }
117
+ }else{
118
+ res.statusCode = 403;
119
+ res.end(msg);
120
+ return false;
121
+ }
122
+ }
123
+
124
+ processLogout(req,res){
125
+ let cookies = new Cookies( req, res );
126
+ let sessionIdCookie = cookies.get('sws-session-id');
127
+ if( (sessionIdCookie !== undefined) && (sessionIdCookie !== null) ){
128
+ if( sessionIdCookie in this.sessionIDs ){
129
+ this.removeSessionID(sessionIdCookie);
130
+ cookies.set('sws-session-id'); // deletes cookie
131
+ }
132
+ }
133
+ res.statusCode = 200;
134
+ res.end('Logged out');
135
+ }
136
+
137
+ }
138
+
139
+ let swsAuth = new SwsAuth();
140
+ module.exports = swsAuth;
@@ -4,17 +4,29 @@
4
4
 
5
5
  'use strict';
6
6
 
7
- var os = require('os');
8
- var util = require('util');
9
- var http = require('http');
10
- var url = require('url');
11
- var request = require('request');
12
-
13
- var debug = require('debug')('sws:elastic');
14
- var swsUtil = require('./swsUtil');
15
- var moment = require('moment');
16
-
17
- var indexTemplate = require('../schema/elasticsearch/api_index_template.json');
7
+ const os = require('os');
8
+ const util = require('util');
9
+ const http = require('http');
10
+ const url = require('url');
11
+ const https = require('https');
12
+ //const axios = require('axios');
13
+ let axios = null;
14
+ let axiosPromise = new Promise(async (resolve) => {
15
+ axios = (await import('axios')).default;
16
+ resolve(axios);
17
+ });
18
+ /*
19
+ (async () => {
20
+ axios = (await import('axios')).default;
21
+ })();
22
+ */
23
+
24
+ const debug = require('debug')('sws:elastic');
25
+ const swsUtil = require('./swsUtil');
26
+ const moment = require('moment');
27
+
28
+ const indexTemplate = require('../schema/elasticsearch/api_index_template.json');
29
+ const indexTemplate7X = require('../schema/elasticsearch/api_index_template_7x.json');
18
30
 
19
31
 
20
32
  const ES_MAX_BUFF = 50;
@@ -25,6 +37,9 @@ function swsElasticEmitter() {
25
37
  // Options
26
38
  this.options = null;
27
39
 
40
+ this.es7 = false;
41
+ this.es8 = true;
42
+
28
43
  this.indexBuffer = '';
29
44
  this.bufferCount = 0;
30
45
  this.lastFlush = 0;
@@ -38,6 +53,9 @@ function swsElasticEmitter() {
38
53
  this.elasticUsername = null;
39
54
  this.elasticPassword = null;
40
55
 
56
+ this.elasticsearchCert = null;
57
+ this.elasticsearchKey = null
58
+
41
59
  this.indexPrefix = "api-";
42
60
 
43
61
  this.enabled = false;
@@ -78,11 +96,26 @@ swsElasticEmitter.prototype.initialize = function (swsOptions) {
78
96
  this.elasticPassword = swsOptions[swsUtil.supportedOptions.elasticsearchPassword];
79
97
  }
80
98
 
81
- // Check / Initialize schema
82
- this.initTemplate();
99
+ if(swsUtil.supportedOptions.elasticsearchCert in swsOptions) {
100
+ this.elasticsearchCert = swsOptions[swsUtil.supportedOptions.elasticsearchCert]
101
+ }
83
102
 
84
- this.enabled = true;
103
+ if( swsUtil.supportedOptions.elasticsearchKey in swsOptions) {
104
+ this.elasticsearchKey = swsOptions[swsUtil.supportedOptions.elasticsearchKey]
105
+ }
106
+
107
+ if(this.elasticsearchKey && this.elasticsearchCert){
108
+ axios.defaults.httpsAgent = new https.Agent({
109
+ rejectUnauthorized: false, // (NOTE: this will disable client verification)
110
+ cert: this.elasticsearchCert,
111
+ key: this.elasticsearchKey,
112
+ });
113
+ }
85
114
 
115
+ // Check / Initialize schema
116
+ Promise.resolve(axiosPromise).then( () => {
117
+ this.initTemplate();
118
+ });
86
119
  };
87
120
 
88
121
  // initialize index template
@@ -90,50 +123,70 @@ swsElasticEmitter.prototype.initTemplate = function(rrr) {
90
123
 
91
124
  var that = this;
92
125
 
93
- var requiredTemplateVersion = indexTemplate.version;
126
+ var requiredTemplateVersion = indexTemplate7X.version;
94
127
 
95
128
  // Check if there is a template
96
129
  var templateURL = this.elasticURL+'/_template/template_api';
97
- var getOptions = {url:templateURL, json:true};
98
- var putOptions = {url:templateURL, json:indexTemplate};
130
+ var getOptionsVersion = {method:'get',url:this.elasticURL};
131
+ var getOptions = {method:'get',url:templateURL};
132
+ let putOptions = {method:'put',url:templateURL, data:indexTemplate7X};
99
133
 
100
134
  if (this.elasticUsername && this.elasticPassword) {
101
135
  var auth = {
102
136
  username: this.elasticUsername,
103
137
  password: this.elasticPassword,
104
138
  }
139
+ getOptionsVersion.auth = auth;
105
140
  getOptions.auth = auth;
106
141
  putOptions.auth = auth;
107
142
  }
108
143
 
109
- request.get(getOptions, function (error, response, body) {
110
- if(error) {
111
- debug("Error querying template:", JSON.stringify(error) );
112
- }else {
144
+ axios(getOptionsVersion).then( (response) => {
145
+ const body = response.data || {};
146
+ if(body && ('version' in body) && ('number' in body.version)){
147
+ that.es7 = body.version.number.startsWith('7');
148
+ that.es8 = body.version.number.startsWith('8');
149
+ }
150
+
151
+ if( !that.es7 && !that.es8){
152
+ putOptions.json = indexTemplate;
153
+ }
113
154
 
114
- var initializeNeeded = false;
155
+ let initializeNeeded = false;
115
156
 
116
- if(response.statusCode === 404){
117
- initializeNeeded = true;
118
- }else if(response.statusCode === 200){
119
- if( 'template_api' in body ) {
120
- if (!('version' in body.template_api) || (body.template_api.version < requiredTemplateVersion)) {
121
- initializeNeeded = true;
122
- }
157
+ axios(getOptions).then( (response) => {
158
+ const body = response.data || {};
159
+ if( 'template_api' in body ) {
160
+ if (!('version' in body.template_api) || (body.template_api.version < requiredTemplateVersion)) {
161
+ initializeNeeded = true;
123
162
  }
124
163
  }
125
-
164
+ }).catch((error)=>{
165
+ if(error.response && error.response.status === 404) {
166
+ initializeNeeded = true;
167
+ } else {
168
+ debug(`Error querying template: ${error.message}`);
169
+ that.enabled = false;
170
+ }
171
+ }).finally(()=> {
126
172
  if(initializeNeeded){
127
- request.put(putOptions, function (error, response, body) {
128
- if(error) {
129
- debug("Failed to update template:", JSON.stringify(error));
130
- }
173
+ axios(putOptions).then((response) =>{
174
+ debug("Elasticsearch template updated");
175
+ that.enabled = true;
176
+ }).catch((error)=>{
177
+ debug(`Failed to update template: ${error.message}`);
178
+ that.enabled = false;
131
179
  });
180
+ }else{
181
+ that.enabled = true;
132
182
  }
183
+ });
133
184
 
134
- }
135
- });
136
185
 
186
+ }).catch((error)=>{
187
+ debug(`Error getting version: ${error.message}`);
188
+ that.enabled = false;
189
+ });
137
190
  };
138
191
 
139
192
  // Update timeline and stats per tick
@@ -180,7 +233,11 @@ swsElasticEmitter.prototype.processRecord = function(rrr){
180
233
 
181
234
  // Create metadata
182
235
  var indexName = this.indexPrefix+moment(rrr['@timestamp']).utc().format('YYYY.MM.DD');
183
- var meta = {index:{_index:indexName,_type:'api',_id:rrr.id}};
236
+
237
+ let meta = {index:{_index:indexName,_id:rrr.id}};
238
+ if(!this.es7 && !this.es8){
239
+ meta = {index:{_index:indexName,_type:'api',_id:rrr.id}};
240
+ }
184
241
 
185
242
  // Add to buffer
186
243
  this.indexBuffer += JSON.stringify(meta) + '\n';
@@ -201,12 +258,13 @@ swsElasticEmitter.prototype.flush = function(){
201
258
 
202
259
  this.lastFlush = Date.now();
203
260
 
204
- var options = {
261
+ let options = {
262
+ method: 'post',
205
263
  url: this.elasticURLBulk,
206
264
  headers: {
207
265
  'Content-Type': 'application/x-ndjson'
208
266
  },
209
- body: this.indexBuffer
267
+ data: this.indexBuffer,
210
268
  };
211
269
 
212
270
  if (this.elasticUsername && this.elasticPassword) {
@@ -216,13 +274,13 @@ swsElasticEmitter.prototype.flush = function(){
216
274
  }
217
275
  }
218
276
 
219
- request.post(options, function (error, response, body) {
220
- if (error) {
221
- debug("Indexing Error:", JSON.stringify(error) );
222
- }
223
- if (response && ('statusCode' in response) && (response.statusCode !== 200)) {
224
- debug('Indexing Error: %d %s',response.statusCode, response.message);
277
+ axios(options).then((response)=> {
278
+ if (response && ('status' in response) && (response.status !== 200)) {
279
+ debug('Indexing Error: %d %s',response.status, response.message);
225
280
  }
281
+ }).catch((error)=>{
282
+ debug(`Indexing Error: ${error.message}`);
283
+ that.enabled = false;
226
284
  });
227
285
 
228
286
  this.indexBuffer = '';
package/lib/swsHapi.js CHANGED
@@ -3,6 +3,7 @@ const path = require('path');
3
3
  const promClient = require("prom-client");
4
4
  const swsSettings = require('./swssettings');
5
5
  const swsProcessor = require('./swsProcessor');
6
+ const swsAuth = require('./swsAuth');
6
7
  const swsUtil = require('./swsUtil');
7
8
  const debug = require('debug')('sws:hapi');
8
9
  const url = require('url');
@@ -33,7 +34,7 @@ class SwsHapi {
33
34
  debug("processResponse:ERROR: " + e);
34
35
  }
35
36
  });
36
- await server.ext('onRequest', function (request, h) {
37
+ await server.ext('onRequest', async function (request, h) {
37
38
  let nodeReq = request.raw.req;
38
39
  let nodeRes = request.raw.res;
39
40
  nodeRes._swsReq = nodeReq;
@@ -43,6 +44,14 @@ class SwsHapi {
43
44
  if(reqUrl.startsWith(swsSettings.uriPath)){
44
45
  // Don't track sws requests
45
46
  nodeReq.sws.track = false;
47
+ /*
48
+ if(reqUrl.startsWith(swsSettings.pathStats)){
49
+ let authResult = await swsAuth.processAuth(request.raw.req,request.raw.res);
50
+ if( authResult ){
51
+ //return h.continue;
52
+ return processor.getStats(request.raw.req.sws.query);
53
+ }
54
+ }*/
46
55
  return h.continue;
47
56
  }
48
57
  try {
@@ -56,7 +65,14 @@ class SwsHapi {
56
65
  server.route({
57
66
  method: 'GET',
58
67
  path: swsSettings.pathStats,
59
- handler: function (request, h) {
68
+ handler: async function (request, h) {
69
+ let authResult = await swsAuth.processAuth(request.raw.req,request.raw.res);
70
+ if( !authResult ){
71
+ return h.abandon;
72
+ }
73
+ if(('sws-auth' in request.raw.req) && request.raw.req['sws-auth']){
74
+ request.raw.res.setHeader('x-sws-authenticated','true');
75
+ }
60
76
  return processor.getStats(request.raw.req.sws.query);
61
77
  },
62
78
  options: options.routeOptions
@@ -65,45 +81,24 @@ class SwsHapi {
65
81
  server.route({
66
82
  method: 'GET',
67
83
  path: swsSettings.pathMetrics,
68
- handler: function (request, h) {
69
- const response = h.response(promClient.register.metrics());
84
+ handler: async function (request, h) {
85
+ let authResult = await swsAuth.processAuth(request.raw.req,request.raw.res);
86
+ if( !authResult ){
87
+ return h.abandon;
88
+ }
89
+ const response = h.response(await promClient.register.metrics());
70
90
  response.code(200);
71
91
  response.header('Content-Type', 'text/plain');
72
92
  return response;
73
93
  },
74
94
  options: options.routeOptions
75
95
  });
76
- // Redirect to ui
77
- server.route({
78
- method: 'GET',
79
- path: swsSettings.uriPath,
80
- handler: function (request, h) {
81
- return h.redirect(swsSettings.pathUI);
82
- },
83
- options: options.routeOptions
84
- });
85
- // Return UI
96
+ // Logout
86
97
  server.route({
87
98
  method: 'GET',
88
- path: swsSettings.pathUI,
99
+ path: swsSettings.pathLogout,
89
100
  handler: function (request, h) {
90
- return swsUtil.swsEmbeddedUIMarkup;
91
- },
92
- options: options.routeOptions
93
- });
94
- // Return Dist
95
- server.route({
96
- method: 'GET',
97
- path: swsSettings.pathDist+'/{file*}',
98
- handler: function (request, h) {
99
- let fileName = request.params.file;
100
- var options = {
101
- root: path.join(__dirname,'..','dist'),
102
- dotfiles: 'deny'
103
- // TODO Caching
104
- };
105
- request.raw.res.setHeader('Content-Type', send.mime.lookup(path.basename(fileName)));
106
- send(request.raw.req, fileName, options).pipe(request.raw.res);
101
+ swsAuth.processLogout(request.raw.req,request.raw.res);
107
102
  return h.abandon;
108
103
  },
109
104
  options: options.routeOptions
@@ -111,13 +106,13 @@ class SwsHapi {
111
106
  // Return UX
112
107
  server.route({
113
108
  method: 'GET',
114
- path: swsSettings.pathUX+'/{file*}',
109
+ path: swsSettings.pathUX+'{file*}',
115
110
  handler: function (request, h) {
116
111
  let fileName = request.params.file;
117
112
  if(!fileName){
118
113
  fileName = 'index.html';
119
114
  }
120
- var options = {
115
+ let options = {
121
116
  root: path.join(__dirname,'..','ux'),
122
117
  dotfiles: 'deny'
123
118
  // TODO Caching