Skip to content

Commit d36c1ef

Browse files
Robin BuschmannRobin Buschmann
authored andcommitted
error handling improved
1 parent ed9958d commit d36c1ef

15 files changed

+132
-56
lines changed

api/ApiAbstract.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,14 @@ export abstract class ApiAbstract extends WebSocket {
150150

151151
return constructor.name.replace(PREFIX, '').toLocaleLowerCase();
152152
}
153-
153+
154154
getPlugs(req: express.Request, res: express.Response, next: any): void {
155-
155+
156156
throw new NotImplementedError();
157157
}
158-
158+
159159
getChargingFacilities(req: express.Request, res: express.Response, next: any): void {
160-
160+
161161
throw new NotImplementedError();
162162
}
163163

@@ -172,6 +172,11 @@ export abstract class ApiAbstract extends WebSocket {
172172
next();
173173
}
174174

175+
processErrors(err: any, req: express.Request, res: express.Response, next: any) {
176+
177+
res.sendStatus(HttpStatus.InternalServerError);
178+
}
179+
175180
// Helper
176181
// ===============================
177182

api/ApiV1.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {ApiAbstract} from "./ApiAbstract";
1111
import {CronService} from "../services/CronService";
1212
import {EVSEService} from "../services/EVSEService";
1313
import {UserService} from "../services/UserService";
14-
import {ParametersMissingError} from "../errors/ParametersMissingError";
1514
import {BadRequestError} from "../errors/BadRequestError";
1615
import {config} from "../config";
1716
import {IApiRequest} from "../interfaces/IApiRequest";
@@ -22,6 +21,8 @@ import {UserChargingService} from "../services/UserChargingService";
2221
import {UtilityService} from "../services/UtilityService";
2322
import {PlugService} from "../services/PlugService";
2423
import {ChargingFacilityService} from "../services/ChargingFacilityService";
24+
import {db} from "../db";
25+
import {logger} from "../logger";
2526
const request = require('request');
2627

2728
@Inject
@@ -98,13 +99,7 @@ export class ApiV1 extends ApiAbstract {
9899
const data = req.body;
99100

100101
Promise.resolve()
101-
.then(() => {
102-
103-
if (!data.languageCode) {
104-
105-
throw new ParametersMissingError(['languageCode']);
106-
}
107-
})
102+
.then(() => this.checkRequiredParameters(data, ['languageCode']))
108103
.then(() => this.userService.registerOrAuthenticate(
109104
data.languageCode, data.providerId, data.evcoId, data.password))
110105
.then((user) => res.json(user))
@@ -376,6 +371,46 @@ export class ApiV1 extends ApiAbstract {
376371
.catch(next)
377372
}
378373

374+
processErrors(err: any, req: express.Request, res: express.Response, next: any): any {
375+
376+
// log errors
377+
// ------------------
378+
logger.error(err);
379+
380+
// http response
381+
// ------------------
382+
383+
// Security header for content sniffing
384+
res.setHeader('X-Content-Type-Options', 'nosniff');
385+
386+
err = err || {message: 'unknown'};
387+
const status = err.statusCode || HttpStatus.InternalServerError;
388+
const secureToShow = err.secureToShow;
389+
390+
delete err.secureToShow;
391+
delete err.statusCode;
392+
393+
if (secureToShow) {
394+
395+
res
396+
.status(status)
397+
.json(err)
398+
;
399+
} else {
400+
401+
if (config.environment === 'development') {
402+
403+
res
404+
.status(status)
405+
.send(err && err.toString ? err.toString() : '')
406+
;
407+
} else {
408+
409+
res.sendStatus(status);
410+
}
411+
}
412+
}
413+
379414
// WebSocket namespaces
380415
// ===============================
381416

app.ts

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ import path = require('path');
1010

1111
import {IApiRequest} from "./interfaces/IApiRequest";
1212
import {config} from "./config";
13+
import {logger} from "./logger";
1314
import {ApiAbstract} from "./api/ApiAbstract";
1415
import apis from "./api/api";
15-
import {logger} from "./logger";
16-
import {Injector} from 'di-ts';
17-
import {DataImporter} from "./services/DataImporter";
18-
import {SoapService} from "./services/SoapService";
1916

2017
const nodeadmin = require('nodeadmin');
21-
const errorHandler = require('errorhandler');
2218
const app = express();
2319

20+
// GENERAL CONFIGURATIONS
21+
// ----------------------------------------------
22+
app.disable('x-powered-by');
23+
2424

2525
// EXPRESS ENVIRONMENT VARIABLES
2626
// ----------------------------------------------
@@ -46,12 +46,7 @@ app.use(methodOverride('X-HTTP-Method-Override'));
4646
// middleware for api documentation
4747
app.use(express.static(path.join(__dirname, 'documentation')));
4848

49-
// middleware showing errors as http response (errors will only shon in dev mode)
50-
if ('development' === app.get('env')) {
51-
app.use(errorHandler())
52-
}
53-
54-
// admin tool, accessible through "NodeAdmin/"
49+
// admin tool, accessible via "NodeAdmin/"
5550
app.use(nodeadmin(app));
5651

5752

@@ -121,27 +116,13 @@ app.get('/:apiVersion/charging-locations', (req: IApiRequest, res, next) => req.
121116
app.get('/:apiVersion/charging-locations/:id', (req: IApiRequest, res, next) => req.api.getChargingLocation(req, res, next));
122117
app.get('/:apiVersion/charging-locations/:id/evses', (req: IApiRequest, res, next) => req.api.getChargingLocationEVSEs(req, res, next));
123118

119+
// error handler
120+
app.use((err, req: IApiRequest, res, next) => req.api.processErrors(err, req, res, next));
121+
124122

125123
// SERVER CREATION AND EXECUTION
126124
// ----------------------------------------------
127125
http.createServer(app).listen(
128126
app.get('port'),
129127
() => logger.info('Server listening on port ' + app.get('port'))
130128
);
131-
132-
133-
// SOME PREPARATION FOR DEVELOPMENT
134-
// ----------------------------------------------
135-
136-
if ('development' === app.get('env')) {
137-
138-
if (config.dev.importMockData) {
139-
140-
const injector = new Injector();
141-
const dataImporter = injector.get(DataImporter);
142-
143-
dataImporter.execute(require('./evseDataMock.json'))
144-
.then(() => logger.info('(DEV) mock data successfully imported'))
145-
.catch(err => logger.error('(DEV) mock data could not have been imported', err));
146-
}
147-
}

config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export var config = {
2121
},
2222
soap: {
2323
initialize: getEnvVariable('SOAP_INIT') === 'true',
24-
timeout: 1000 * 60 * 5,
24+
timeout: 1000 * 60 * 15, // 15min
2525
providerId: 'DE*ICE',
2626
geoFormat: 'Google',
2727
authorizeEvseId: 'DE*APP*E000123',

errors/BadRequestError.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
export class BadRequestError extends Error {
1+
import {BaseError} from "./BaseError";
2+
3+
export class BadRequestError extends BaseError {
24

35
statusCode = HttpStatus.BadRequest;
46

57
constructor(public message: string){
6-
super();
8+
9+
super(true);
710
}
811

912
}

errors/BaseError.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export class BaseError extends Error {
2+
3+
constructor(
4+
// indicates if this error can be passed to the client
5+
public secureToShow: boolean
6+
) {
7+
super();
8+
}
9+
10+
}

errors/HubjectError.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {BaseError} from "./BaseError";
2+
3+
export class HubjectError extends BaseError {
4+
5+
constructor(public hubjectErrorCode: string,
6+
public message: string,
7+
public statusCode: HttpStatus) {
8+
9+
super(true);
10+
}
11+
}

errors/InvalidDataError.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
export class InvalidDataError extends Error {
1+
import {BaseError} from "./BaseError";
2+
3+
export class InvalidDataError extends BaseError {
24

35
statusCode = HttpStatus.BadRequest;
46

57
constructor(public message: string){
6-
super();
8+
9+
super(true);
710
}
811

912
}

errors/NotAuthorizedError.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
export class NotAuthorizedError extends Error {
2-
1+
import {BaseError} from "./BaseError";
2+
3+
export class NotAuthorizedError extends BaseError {
4+
35
statusCode = HttpStatus.Unauthorized;
46

57
constructor(public message: string) {
6-
super(message);
8+
9+
super(true);
710
}
811
}

errors/NotImplementedError.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import {BaseError} from "./BaseError";
12

2-
export class NotImplementedError extends Error {
3+
export class NotImplementedError extends BaseError {
34

45
statusCode = HttpStatus.NotFound;
56
message: string = 'This resource is not implemented on this version';
67

8+
constructor() {
9+
10+
super(true);
11+
}
712
}

0 commit comments

Comments
 (0)