forked from getsentry/sentry-electron
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.ts
119 lines (103 loc) · 3.38 KB
/
server.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// tslint:disable:no-unsafe-any
import { Event } from '@sentry/types';
import bodyParser = require('body-parser');
import express = require('express');
import finalhandler = require('finalhandler');
import multer = require('multer');
import { createServer, Server } from 'http';
/** Event payload that has been submitted to the test server. */
export interface TestServerEvent {
/** Request ID (UUID) */
id: string;
/** Public auth key from the DSN. */
sentry_key: string;
/** Sentry Event data (should conform to the SentryEvent interface). */
data: Event;
/** An optional minidump file, if included in the event. */
dump_file?: boolean;
}
/**
* A mock Sentry server.
*
* Use `server.start()` to start execution and `server.stop()` to terminate it.
*/
export class TestServer {
/** All events received by this server instance. */
public events: TestServerEvent[] = [];
/** The internal HTTP server. */
private _server?: Server;
/** Starts accepting requests. */
public start(): void {
const upload = multer({ storage: multer.memoryStorage() });
const app = express();
app.use(
// eslint-disable-next-line deprecation/deprecation
bodyParser.raw({
inflate: true,
limit: '200mb',
type: 'application/x-sentry-envelope',
}),
);
// Handles the Sentry envelope endpoint
app.post('/api/:id/envelope', (req, res) => {
const auth = (req.headers['x-sentry-auth'] as string) || '';
const keyMatch = auth.match(/sentry_key=([a-f0-9]*)/);
if (!keyMatch) {
res.status(400);
res.end('Missing authentication header');
return;
}
const envelope = req.body.toString().split('\n');
this.events.push({
data: JSON.parse(envelope[2]) as Event,
dump_file: envelope[4] !== undefined,
id: req.params.id,
sentry_key: keyMatch[1],
});
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end('Success');
});
app.post('/api/:id/minidump', upload.fields([{ name: 'upload_file_minidump' }]), (req, res) => {
const auth = (req.headers['x-sentry-auth'] as string) || '';
const keyMatch = auth.match(/sentry_key=([a-f0-9]*)/);
if (!keyMatch) {
res.status(400);
res.end('Missing authentication header');
return;
}
const files = req.files as { [fieldName: string]: Express.Multer.File[] };
this.events.push({
data: JSON.parse(req.body.sentry) as Event,
dump_file: Boolean(files.upload_file_minidump[0]),
id: req.params.id,
sentry_key: keyMatch[1],
});
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.end('Success');
});
this._server = createServer((req, res) => {
app(req as any, res as any, finalhandler(req, res));
});
// Changed to port to 8123 because sentry uses 8000 if run locally
this._server.listen(8123);
}
public clearEvents(): void {
this.events = [];
}
/** Stops accepting requests and closes the server. */
public async stop(): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (this._server) {
this._server.close(e => {
if (e) {
reject(e);
} else {
resolve();
}
});
} else {
reject(new Error('Invariant violation: Call .start() first'));
}
});
}
}