Handle properly Axios error
MODIFY
src/client/ocpi/CpoOCPIClient.ts
src/client/ocpi/CpoOCPIClient.ts
-import ChargingStation, { Connector } from '../../types/ChargingStation';
-import { OCPIAllowed, OCPIAuthorizationInfo } from '../../types/ocpi/OCPIAuthorizationInfo';
-import { OCPIAuthMethod, OCPISession, OCPISessionStatus } from '../../types/ocpi/OCPISession';
-import { OCPILocation, OCPILocationReference } from '../../types/ocpi/OCPILocation';
-
+import axios, { AxiosResponse } from 'axios';
+import axiosRetry from 'axios-retry';
+import _ from 'lodash';
+import moment from 'moment';
import BackendError from '../../exception/BackendError';
-import Constants from '../../utils/Constants';
-import Logging from '../../utils/Logging';
import NotificationHandler from '../../notification/NotificationHandler';
+import OCPIMapping from '../../server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIMapping';
+import OCPITokensService from '../../server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPITokensService';
+import OCPIUtils from '../../server/ocpi/OCPIUtils';
+import OCPIEndpointStorage from '../../storage/mongodb/OCPIEndpointStorage';
+import OCPPStorage from '../../storage/mongodb/OCPPStorage';
+import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage';
+import SiteStorage from '../../storage/mongodb/SiteStorage';
+import TenantStorage from '../../storage/mongodb/TenantStorage';
+import TransactionStorage from '../../storage/mongodb/TransactionStorage';
+import ChargingStation, { Connector } from '../../types/ChargingStation';
+import { OCPIAllowed, OCPIAuthorizationInfo } from '../../types/ocpi/OCPIAuthorizationInfo';
import { OCPICdr } from '../../types/ocpi/OCPICdr';
-import OCPIClient from './OCPIClient';
import OCPIEndpoint from '../../types/ocpi/OCPIEndpoint';
-import OCPIEndpointStorage from '../../storage/mongodb/OCPIEndpointStorage';
import { OCPIEvseStatus } from '../../types/ocpi/OCPIEvse';
import { OCPIJobResult } from '../../types/ocpi/OCPIJobResult';
-import OCPIMapping from '../../server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPIMapping';
+import { OCPILocation, OCPILocationReference } from '../../types/ocpi/OCPILocation';
import { OCPIRole } from '../../types/ocpi/OCPIRole';
+import { OCPIAuthMethod, OCPISession, OCPISessionStatus } from '../../types/ocpi/OCPISession';
import { OCPIToken } from '../../types/ocpi/OCPIToken';
-import OCPITokensService from '../../server/ocpi/ocpi-services-impl/ocpi-2.1.1/OCPITokensService';
-import OCPIUtils from '../../server/ocpi/OCPIUtils';
-import OCPPStorage from '../../storage/mongodb/OCPPStorage';
-import { OcpiSetting } from '../../types/Setting';
import { ServerAction } from '../../types/Server';
+import { OcpiSetting } from '../../types/Setting';
import Site from '../../types/Site';
-import SiteAreaStorage from '../../storage/mongodb/SiteAreaStorage';
-import SiteStorage from '../../storage/mongodb/SiteStorage';
import Tenant from '../../types/Tenant';
-import TenantStorage from '../../storage/mongodb/TenantStorage';
import Transaction from '../../types/Transaction';
-import TransactionStorage from '../../storage/mongodb/TransactionStorage';
+import Constants from '../../utils/Constants';
+import Logging from '../../utils/Logging';
import Utils from '../../utils/Utils';
-import _ from 'lodash';
-import axios from 'axios';
-import axiosRetry from 'axios-retry';
-import moment from 'moment';
+import OCPIClient from './OCPIClient';
+
const MODULE_NAME = 'CpoOCPIClient';
@@ -258,22 +258,20 @@ export default class CpoOCPIClient extends OCPIClient {
detailedMessages: { payload: ocpiSession }
});
// Call IOP
- // eslint-disable-next-line no-case-declarations
- const response = await axios.put(sessionsUrl, ocpiSession,
+ let response: AxiosResponse;
+ try {
+ response = await axios.put(sessionsUrl, ocpiSession,
{
headers: {
'Authorization': `Token ${this.ocpiEndpoint.token}`,
'Content-Type': 'application/json'
},
timeout: 10000
- });
- if (response.status !== 200 || !response.data) {
- throw new BackendError({
- action: ServerAction.OCPI_PUSH_SESSIONS,
- message: `Start session failed with status ${response.status}`,
- module: MODULE_NAME, method: 'startSession',
- detailedMessages: { payload: response.data }
- });
+ }
+ );
+ } catch (error) {
+ // Handle errors
+ Utils.handleAxiosError(error, sessionsUrl, ServerAction.OCPI_PUSH_SESSIONS, MODULE_NAME, 'startSession');
}
transaction.ocpiData = {
session: ocpiSession

MODIFY
src/server/ocpp/validation/OCPPValidation.ts
src/server/ocpp/validation/OCPPValidation.ts
@@ -39,10 +39,10 @@ export default class OCPPValidation extends SchemaValidator {
return OCPPValidation.instance;
}
- validateHeartbeat(heartbeat: OCPPHeartbeatRequestExtended) {
+ validateHeartbeat(heartbeat: OCPPHeartbeatRequestExtended): void {
}
- validateStatusNotification(statusNotification: OCPPStatusNotificationRequestExtended) {
+ validateStatusNotification(statusNotification: OCPPStatusNotificationRequestExtended): void {
// Check non mandatory or wrong timestamp
if (!statusNotification.timestamp || new Date(statusNotification.timestamp).getFullYear() === new Date(0).getFullYear()) {
statusNotification.timestamp = new Date().toISOString();
@@ -50,21 +50,23 @@ export default class OCPPValidation extends SchemaValidator {
this.validate(this._statusNotificationRequest, statusNotification);
}
- validateAuthorize(authorize: OCPPAuthorizeRequestExtended) {
+ validateAuthorize(authorize: OCPPAuthorizeRequestExtended): void {
this.validate(this._authorizeRequest, authorize);
}
- validateBootNotification(bootNotification: OCPPBootNotificationRequestExtended) {
+ validateBootNotification(bootNotification: OCPPBootNotificationRequestExtended): void {
this.validate(this._bootNotificationRequest, bootNotification);
}
- validateDiagnosticsStatusNotification(chargingStation: ChargingStation, diagnosticsStatusNotification: OCPPDiagnosticsStatusNotificationRequestExtended) {
+ validateDiagnosticsStatusNotification(chargingStation: ChargingStation,
+ diagnosticsStatusNotification: OCPPDiagnosticsStatusNotificationRequestExtended): void {
}
- validateFirmwareStatusNotification(chargingStation: ChargingStation, firmwareStatusNotification: OCPPFirmwareStatusNotificationRequestExtended) {
+ validateFirmwareStatusNotification(chargingStation: ChargingStation,
+ firmwareStatusNotification: OCPPFirmwareStatusNotificationRequestExtended): void {
}
- validateStartTransaction(chargingStation: ChargingStation, startTransaction) {
+ validateStartTransaction(chargingStation: ChargingStation, startTransaction): void {
this.validate(this._startTransactionRequest, startTransaction);
// Check Connector ID
if (!Utils.getConnectorFromID(chargingStation, startTransaction.connectorId)) {
@@ -77,10 +79,10 @@ export default class OCPPValidation extends SchemaValidator {
}
}
- validateDataTransfer(chargingStation: ChargingStation, dataTransfer: OCPPDataTransferRequestExtended) {
+ validateDataTransfer(chargingStation: ChargingStation, dataTransfer: OCPPDataTransferRequestExtended): void {
}
- validateStopTransaction(chargingStation: ChargingStation, stopTransaction: OCPPStopTransactionRequestExtended) {
+ validateStopTransaction(chargingStation: ChargingStation, stopTransaction: OCPPStopTransactionRequestExtended): void {
if (chargingStation.ocppVersion === OCPPVersion.VERSION_16) {
this.validate(this._stopTransactionRequest16, stopTransaction);
} else {
@@ -88,7 +90,7 @@ export default class OCPPValidation extends SchemaValidator {
}
}
- validateMeterValues(tenantID: string, chargingStation: ChargingStation, meterValues: OCPPMeterValuesExtended) {
+ validateMeterValues(tenantID: string, chargingStation: ChargingStation, meterValues: OCPPMeterValuesExtended): void {
// Always integer
meterValues.connectorId = Utils.convertToInt(meterValues.connectorId);
// Check Connector ID

MODIFY
src/server/rest/service/AuthService.ts
src/server/rest/service/AuthService.ts
@@ -20,7 +20,7 @@ import UserStorage from '../../../storage/mongodb/UserStorage';
import UserToken from '../../../types/UserToken';
import Utils from '../../../utils/Utils';
import UtilsService from './UtilsService';
-import axios from 'axios';
+import axios, { AxiosResponse } from 'axios';
import axiosRetry from 'axios-retry';
import jwt from 'jsonwebtoken';
import moment from 'moment';
@@ -330,8 +330,14 @@ export default class AuthService {
});
}
// Check captcha
- const response = await axios.get(
- `https://www.google.com/recaptcha/api/siteverify?secret=${_centralSystemRestConfig.captchaSecretKey}&response=${filteredRequest.captcha}&remoteip=${req.connection.remoteAddress}`);
+ let response: AxiosResponse;
+ const axiosURL = `https://www.google.com/recaptcha/api/siteverify?secret=${_centralSystemRestConfig.captchaSecretKey}&response=${filteredRequest.captcha}&remoteip=${req.connection.remoteAddress}`;
+ try {
+ response = await axios.get(axiosURL);
+ } catch (error) {
+ // Handle errors
+ Utils.handleAxiosError(error, axiosURL, action, MODULE_NAME, 'handleRegisterUser');
+ }
// Check
if (!response.data.success) {
throw new AppError({

MODIFY
src/utils/Logging.ts
src/utils/Logging.ts
@@ -380,7 +380,7 @@ export default class Logging {
// Check that every detailedMessages is parsed
return JSON.stringify(detailedMessage, null, ' ');
} catch (err) {
- // Do nothing
+ return detailedMessage;
}
}
}

MODIFY
src/utils/Utils.ts
src/utils/Utils.ts
-import { AnalyticsSettingsType, AssetSettingsType, BillingSettingsType, PricingSettingsType, RefundSettingsType, RoamingSettingsType, SettingDBContent, SmartChargingContentType } from '../types/Setting';
-import { Car, CarCatalog, CarType } from '../types/Car';
-import { ChargePointStatus, OCPPProtocol, OCPPVersion } from '../types/ocpp/OCPPServer';
-import ChargingStation, { ChargePoint, Connector, ConnectorCurrentLimitSource, CurrentType } from '../types/ChargingStation';
-import Transaction, { InactivityStatus } from '../types/Transaction';
-import User, { UserRole, UserStatus } from '../types/User';
-
-import { ActionsResponse } from '../types/GlobalType';
-import Address from '../types/Address';
-import AppError from '../exception/AppError';
-import Asset from '../types/Asset';
+import { AxiosError } from 'axios';
+import bcrypt from 'bcryptjs';
+import crypto from 'crypto';
+import { Request } from 'express';
+import fs from 'fs';
+import http from 'http';
+import _ from 'lodash';
+import moment from 'moment';
+import { ObjectID } from 'mongodb';
+import passwordGenerator from 'password-generator';
+import path from 'path';
+import tzlookup from 'tz-lookup';
+import url from 'url';
+import { v4 as uuid } from 'uuid';
+import validator from 'validator';
import Authorizations from '../authorization/Authorizations';
+import AppError from '../exception/AppError';
import BackendError from '../exception/BackendError';
+import TenantStorage from '../storage/mongodb/TenantStorage';
+import UserStorage from '../storage/mongodb/UserStorage';
+import Address from '../types/Address';
+import Asset from '../types/Asset';
+import { Car, CarCatalog, CarType } from '../types/Car';
import { ChargingProfile } from '../types/ChargingProfile';
+import ChargingStation, { ChargePoint, Connector, ConnectorCurrentLimitSource, CurrentType } from '../types/ChargingStation';
import Company from '../types/Company';
-import Configuration from './Configuration';
import ConnectorStats from '../types/ConnectorStats';
-import Constants from './Constants';
-import Cypher from './Cypher';
+import { ActionsResponse } from '../types/GlobalType';
import { HTTPError } from '../types/HTTPError';
-import Logging from './Logging';
import OCPIEndpoint from '../types/ocpi/OCPIEndpoint';
-import { ObjectID } from 'mongodb';
-import { Request } from 'express';
+import { ChargePointStatus, OCPPProtocol, OCPPVersion } from '../types/ocpp/OCPPServer';
import { ServerAction } from '../types/Server';
+import { AnalyticsSettingsType, AssetSettingsType, BillingSettingsType, PricingSettingsType, RefundSettingsType, RoamingSettingsType, SettingDBContent, SmartChargingContentType } from '../types/Setting';
import Site from '../types/Site';
import SiteArea from '../types/SiteArea';
import Tag from '../types/Tag';
import Tenant from '../types/Tenant';
import TenantComponents from '../types/TenantComponents';
-import TenantStorage from '../storage/mongodb/TenantStorage';
-import UserStorage from '../storage/mongodb/UserStorage';
+import Transaction, { InactivityStatus } from '../types/Transaction';
+import User, { UserRole, UserStatus } from '../types/User';
import UserToken from '../types/UserToken';
-import _ from 'lodash';
-import bcrypt from 'bcryptjs';
-import crypto from 'crypto';
-import fs from 'fs';
-import http from 'http';
-import moment from 'moment';
-import passwordGenerator from 'password-generator';
-import path from 'path';
-import tzlookup from 'tz-lookup';
-import url from 'url';
-import { v4 as uuid } from 'uuid';
-import validator from 'validator';
+import Configuration from './Configuration';
+import Constants from './Constants';
+import Cypher from './Cypher';
+import Logging from './Logging';
const MODULE_NAME = 'Utils';
@@ -51,6 +51,45 @@ export default class Utils {
private static centralSystemFrontEndConfig = Configuration.getCentralSystemFrontEndConfig();
private static centralSystemRestServer = Configuration.getCentralSystemRestServer();
+ public static handleAxiosError(axiosError: AxiosError, urlRequest: string, action: ServerAction,
+ module: string, method: string): void {
+ // Handle Error outside 2xx range
+ if (axiosError.response) {
+ throw new BackendError({
+ action, module, method,
+ message: `HTTP error '${axiosError.response.status}' while processing the URL '${urlRequest}'`,
+ detailedMessages: {
+ url: urlRequest,
+ status: axiosError.response.status,
+ axiosError: axiosError.toJSON(),
+ }
+ });
+ } else if (axiosError.request) {
+ // The request was made but no response was received
+ // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
+ // http.ClientRequest in node.js
+ throw new BackendError({
+ action, module, method,
+ message: `HTTP error while processing the URL '${urlRequest}'`,
+ detailedMessages: {
+ url: urlRequest,
+ axiosError: axiosError.toJSON(),
+ }
+ });
+ } else {
+ throw new BackendError({
+ action, module, method,
+ message: `HTTP error while processing the URL '${urlRequest}'`,
+ detailedMessages: {
+ url: urlRequest,
+ message: axiosError.message,
+ stack: axiosError.stack,
+ axiosError: axiosError.toJSON(),
+ }
+ });
+ }
+ }
+
public static isTransactionInProgressOnThreePhases(chargingStation: ChargingStation, transaction: Transaction): boolean {
const currentType = Utils.getChargingStationCurrentType(chargingStation, null, transaction.connectorId);
let threePhases = true;

Handle properly Axios error