• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

telefonicaid / fiware-pep-steelskin / 11211038005

07 Oct 2024 07:51AM UTC coverage: 82.787%. Remained the same
11211038005

Pull #543

github

web-flow
Merge a05a243c2 into b695c594f
Pull Request #543: update doc about accountLogger and pep log level

265 of 349 branches covered (75.93%)

Branch coverage included in aggregate %.

745 of 871 relevant lines covered (85.53%)

52.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.15
/lib/middleware/proxy.js
1
/*
2
 * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U
3
 *
4
 * This file is part of fiware-pep-steelskin
5
 *
6
 * fiware-pep-steelskin is free software: you can redistribute it and/or
7
 * modify it under the terms of the GNU Affero General Public License as
8
 * published by the Free Software Foundation, either version 3 of the License,
9
 * or (at your option) any later version.
10
 *
11
 * fiware-pep-steelskin is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 * See the GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public
17
 * License along with fiware-pep-steelskin.
18
 * If not, seehttp://www.gnu.org/licenses/.
19
 *
20
 * For those usages not covered by the GNU Affero General Public License
21
 * please contact with::[iot_support@tid.es]
22
 */
23

24
'use strict';
25

26
var config = require('../../config'),
1✔
27
    errors = require('../errors'),
28
    request = require('request'),
29
    constants = require('../constants'),
30
    validationHeaders = [
31
        'fiware-service',
32
        'fiware-servicepath',
33
        'x-auth-token'
34
    ],
35
    authorizationHeaders = [
36
        'x-auth-token'
37
    ],
38
    winston = require('winston'),
39
    accessLogger;
40

41
/**
42
 * Middleware to extract the organization data from the request.
43
 *
44
 * @param {Object} req           Incoming request.
45
 * @param {Object} res           Outgoing response.
46
 * @param {Function} next        Call to the next middleware in the chain.
47
 */
48
function extractOrganization(req, res, next) {
1✔
49
    const logger = req.logger;
152✔
50
    if (req.headers[constants.ORGANIZATION_HEADER]) {
152!
51
        req.organization = req.headers[constants.ORGANIZATION_HEADER];
152✔
52
        req.service = req.headers[constants.ORGANIZATION_HEADER];
152✔
53
        req.subService = req.headers[constants.PATH_HEADER];
152✔
54
        next();
152✔
55
    } else {
56
        logger.error('[PROXY-GEN-001] Organization headers not found');
×
57
        next(new errors.OrganizationNotFound());
×
58
    }
59
}
60

61
/**
62
 * Middleware to extract the user data (usually a token) from the request.
63
 *
64
 * @param {Object} req           Incoming request.
65
 * @param {Object} res           Outgoing response.
66
 * @param {Function} next        Call to the next middleware in the chain.
67
 */
68
function extractUserId(req, res, next) {
1✔
69
    const logger = req.logger;
152✔
70
    if (req.headers[constants.AUTHORIZATION_HEADER]) {
152!
71
        req.userId = req.headers[constants.AUTHORIZATION_HEADER];
152✔
72
        next();
152✔
73
    } else {
74
        logger.error('[PROXY-GEN-002] User ID headers not found');
×
75
        next(new errors.UserNotFound());
×
76
    }
77
}
78

79
/**
80
 * Generates the FRN to identify the target resource of the request. The FRN is composed of information from the
81
 * service and subservice headers and some configuration information.
82
 *
83
 * @param {Object} req           Incoming request.
84
 * @param {Object} res           Outgoing response.
85
 * @param {Function} next        Invokes the next middleware in the chain.
86
 */
87
function generateFRN(req, res, next) {
1✔
88
    const logger = req.logger;
153✔
89
    var frn = config.resourceNamePrefix + config.componentName + ':';
153✔
90

91
    if (req.organization) {
153✔
92
        frn += req.organization + ':';
151✔
93
    } else {
94
        frn += ':';
2✔
95
    }
96

97
    if (req.headers[constants.PATH_HEADER]) {
153✔
98
        frn += req.headers[constants.PATH_HEADER] + ':';
152✔
99
    } else {
100
        frn += ':';
1✔
101
    }
102

103
    if (req.resourceUrl) {
153✔
104
        frn += req.resourceUrl + ':';
14✔
105
    } else {
106
        frn += ':';
139✔
107
    }
108

109
    if (req.entityType) {
153!
110
        frn += req.entityType;
×
111
    } else {
112
        frn += ':';
153✔
113
    }
114
    logger.debug('Generated FRN: ', frn);
153✔
115
    req.frn = frn;
153✔
116

117
    next();
153✔
118
}
119

120
/**
121
 * Redirects the incoming request to the proxied host.
122
 * read to guess its type.
123
 *
124
 * @param {Object} req           Incoming request.
125
 * @param {Object} res           Outgoing response.
126
 * @param {Function} next        Invokes the next middleware in the chain.
127
 */
128
function sendRequest(req, res, next) {
1✔
129
    const logger = req.logger;
78✔
130
    var options = {
78✔
131
        uri: 'http://' + config.resource.original.host + ':' + config.resource.original.port + req.path,
132
        qs: req.query,
133
        method: req.method,
134
        headers: req.headers
135
    };
136

137
    if (!options.headers[constants.X_FORWARDED_FOR_HEADER] && req.connection.remoteAddress) {
78✔
138
        options.headers[constants.X_FORWARDED_FOR_HEADER] = req.connection.remoteAddress;
75✔
139
    }
140
    if (!options.headers[constants.CORRELATOR_HEADER] && req.corr) {
78✔
141
        options.headers[constants.CORRELATOR_HEADER] = req.corr;
5✔
142
    }
143

144
    if (req.is('*/json')) {
78✔
145
        options.body = JSON.stringify(req.body);
77✔
146
    } else {
147
        options.body = req.rawBody;
1✔
148
    }
149

150
    delete options.headers['content-length'];
78✔
151
    options.headers.connection = 'close';
78✔
152

153
    res.oldWriteHead = res.writeHead;
78✔
154
    res.writeHead = function(statusCode, reasonPhrase, headers) {
78✔
155
        if (res._headers['transfer-encoding']) {
78!
156
            delete res._headers['transfer-encoding'];
×
157
        }
158

159
        res.oldWriteHead(statusCode, reasonPhrase, headers);
78✔
160
    };
161

162
    logger.debug('Forwarding request:\n\n%j\n', options);
78✔
163

164
    req.fwdResponse = request(options).on('error', function handleConnectionError(e) {
78✔
165
        logger.error('Error forwarding the request to target proxy: %s', e.message);
1✔
166

167
        if (config.dieOnRedirectError) {
1!
168
            logger.fatal('[PROXY-FATAL-001] Configured to die upon error in a redirection. Stopping process.');
×
169

170
            process.exit(-1);
×
171
        } else {
172
            next(new errors.TargetServerError(e.message));
1✔
173
        }
174
    });
175
    next();
78✔
176
}
177

178
/**
179
 * Account Log
180
 * read to guess its type.
181
 *
182
 * @param {Object} req           Incoming request.
183
 * @param {Object} res           Outgoing response.
184
 * @param {Function} next        Invokes the next middleware in the chain.
185
 */
186
function accountInfo(req, res, next) {
1✔
187
    if ('fwdResponse' in req) {
×
188
        if (!accessLogger) {
×
189
            accessLogger = new winston.Logger({
×
190
                level: 'info',
191
                transports: [
192
                    new(winston.transports.File)({
193
                        filename: config.access.accountFile
194
                    })
195
                ]
196
            });
197
        }
198
        req.fwdResponse = req.fwdResponse.on('response', function(res) {
×
199
            accessLogger.info('Right Attempt' +
×
200
                              ' | ResponseStatus=' + req.fwdResponse.response.statusCode +
201
                              ' | Token=' + req.headers['x-auth-token'] +
202
                              ' | Origin=' + req.connection.remoteAddress +
203
                              ' | UserId=' + req.userId +
204
                              ' | ServiceId=' + req.serviceId +
205
                              ' | Service=' + req.service +
206
                              ' | SubServiceId=' + req.subserviceId +
207
                              ' | SubService=' + req.subService +
208
                              ' | Action=' + req.action +
209
                              ' | Date=' + new Date().toJSON());
210
        });
211
    }
212
    next();
×
213
}
214

215
/**
216
 * Invoque request and get response. The request is not read with a pipe, as it has been completely
217
 * read to guess its type.
218
 *
219
 * @param {Object} req           Incoming request.
220
 * @param {Object} res           Outgoing response.
221
 * @param {Function} next        Invokes the next middleware in the chain.
222
 */
223
function sendResponse(req, res, next) {
1✔
224
    req.fwdResponse.pipe(res);
78✔
225
}
226

227
/**
228
 * Generates a middleware that checks for the pressence of the mandatory headers passed as a parameter, returning a
229
 * MISSING_HEADERS error if any one is not found.
230
 *
231
 * @param {Array} mandatoryHeaders      List of headers to check.
232
 * @return {Function}                  An express middleware that checks for the presence of the headers.
233
 */
234
function checkMandatoryHeaders(mandatoryHeaders) {
1✔
235
    return function(req, res, next) {
2✔
236
        var missing = [];
165✔
237

238
        for (var i = 0; i < mandatoryHeaders.length; i++) {
165✔
239
            if (!req.headers[mandatoryHeaders[i]] || req.headers[mandatoryHeaders[i]].trim() === '') {
489✔
240
                missing.push(mandatoryHeaders[i]);
15✔
241
            }
242
        }
243

244
        if (missing.length !== 0) {
165✔
245
            next(new errors.MissingHeaders(JSON.stringify(missing)));
11✔
246
        } else {
247
            next();
154✔
248
        }
249
    };
250
}
251

252
exports.generateFRN = generateFRN;
1✔
253
exports.extractUserId = extractUserId;
1✔
254
exports.extractOrganization = extractOrganization;
1✔
255
exports.sendRequest = sendRequest;
1✔
256
exports.sendResponse = sendResponse;
1✔
257
exports.accountInfo = accountInfo;
1✔
258
exports.checkMandatoryHeaders = checkMandatoryHeaders(validationHeaders);
1✔
259
exports.checkAuthorizationHeader = checkMandatoryHeaders(authorizationHeaders);
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc