1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var async = require('async');
|
8 | var Quota = require('volos-quota-apigee');
|
9 | var debug = require('debug')('gateway:quota');
|
10 | var url = require('url');
|
11 |
|
12 |
|
13 | module.exports.init = function(config /*, logger, stats */) {
|
14 |
|
15 | const { product_to_proxy, proxies } = config;
|
16 | const prodsObj = {};
|
17 | var quotas = {};
|
18 | var options = {
|
19 | key: function(req) {
|
20 | return req.token.application_name+'.'+req.productName;
|
21 | }
|
22 | };
|
23 |
|
24 | var quotaManagers = {}
|
25 |
|
26 | if ( (product_to_proxy === undefined) || (proxies === undefined) ) {
|
27 |
|
28 | debug("quota plugin did not recieve valid produc-proxy map or list of proxies")
|
29 | return(undefined)
|
30 | }
|
31 |
|
32 | Object.keys(config).forEach(function(productName) {
|
33 | var product = config[productName];
|
34 | if (!product.uri && !product.key && !product.secret && !product.allow && !product.interval || product.interval === "null") {
|
35 |
|
36 | debug('Quota not configured on the API product, skipping. This message is safe to ignore');
|
37 | return;
|
38 | }
|
39 |
|
40 | if ( product.timeUnit === 'month' ) {
|
41 |
|
42 | }
|
43 |
|
44 | const prodProxiesArr = product_to_proxy[productName];
|
45 |
|
46 | const prodObj = {};
|
47 | if (Array.isArray(prodProxiesArr)) {
|
48 | prodProxiesArr.reduce((acc, val) => {
|
49 | acc[val] = true;
|
50 | return acc;
|
51 | }, prodObj);
|
52 | }
|
53 |
|
54 | const basePaths = {};
|
55 |
|
56 | if (Array.isArray(proxies)) {
|
57 | proxies.reduce((acc, prox) => {
|
58 | if (prox.name !== 'edgemicro-auth' && prodObj[prox.name] === true) acc[prox.base_path] = true;
|
59 | return acc;
|
60 | }, basePaths);
|
61 | }
|
62 |
|
63 | prodObj.basePaths = basePaths;
|
64 | prodsObj[productName] = prodObj;
|
65 |
|
66 | config[productName].request = config.request;
|
67 | var quota = Quota.create(config[productName]);
|
68 | quotas[productName] = quota.connectMiddleware().apply(options);
|
69 |
|
70 | quotaManagers[productName] = quota;
|
71 | debug('created quota for', productName);
|
72 | });
|
73 |
|
74 | var middleware = function(req, res, next) {
|
75 |
|
76 | if (!req.token || !req.token.api_product_list || !req.token.api_product_list.length) {
|
77 | return next();
|
78 | }
|
79 |
|
80 | debug('quota checking products', req.token.api_product_list);
|
81 |
|
82 | req.originalUrl = req.originalUrl || req.url;
|
83 |
|
84 | let proxyPath = res.proxy ? res.proxy.base_path : undefined;
|
85 | let proxyUrl = req.url ? url.parse(req.url).pathname : undefined;
|
86 | let matchedPathProxy = proxyPath || proxyUrl || '';
|
87 | debug('matchedPathProxy',matchedPathProxy);
|
88 |
|
89 | const prodList = [];
|
90 | if (Array.isArray(req.token.api_product_list)) {
|
91 | req.token.api_product_list.reduce((acc, prod) => {
|
92 | if (prodsObj[prod] &&
|
93 | prodsObj[prod].basePaths &&
|
94 | prodsObj[prod].basePaths[matchedPathProxy] === true) acc.push(prod);
|
95 | return acc;
|
96 | }, prodList);
|
97 |
|
98 | debug('prodList', prodList);
|
99 | }
|
100 |
|
101 |
|
102 |
|
103 | async.eachSeries(prodList,
|
104 | function(productName, cb) {
|
105 | var connectMiddleware = quotas[productName];
|
106 | debug('applying quota for', productName);
|
107 | req['productName'] = productName;
|
108 | if ( connectMiddleware ){ connectMiddleware(req, res, cb) } else cb();
|
109 | },
|
110 | function(err) {
|
111 | next(err);
|
112 | }
|
113 | );
|
114 | }
|
115 |
|
116 | return {
|
117 |
|
118 | testprobe: function() {
|
119 | return quotas
|
120 | },
|
121 |
|
122 | onrequest: function(req, res, next) {
|
123 | if ( process.env.EDGEMICRO_LOCAL !== undefined ) {
|
124 | debug("MG running in local mode. Skipping Quota");
|
125 | next();
|
126 | } else {
|
127 | middleware(req, res, next);
|
128 | }
|
129 | },
|
130 |
|
131 | shutdown: function() {
|
132 |
|
133 | for ( var qmKey in quotaManagers ) {
|
134 | var q = quotaManagers[qmKey];
|
135 | if ( q.quota ) {
|
136 | q = q.quota;
|
137 | }
|
138 | if ( q.bucketTimer ) {
|
139 | clearInterval(q.bucketTimer)
|
140 | }
|
141 | if ( q.flushTimer ) {
|
142 | clearInterval(q.flushTimer)
|
143 | }
|
144 | }
|
145 | }
|
146 |
|
147 | }
|
148 | };
|