-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
153 lines (135 loc) · 4.09 KB
/
server.js
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
const express = require('express');
const axios = require('axios');
const https = require('https');
const redis = require('redis');
const bluebird = require('bluebird');
const morgan = require('morgan');
const helmet = require('helmet');
const Sentry = require('@sentry/node');
Sentry.init({ dsn: process.env.SENTRY_DSN });
const API_URI = 'https://developer.mtd.org/api/v2.2/json';
const CUMTD_API_KEY = process.env.CUMTD_API_KEY;
const MAX_EXPECTED_MINS_AWAY = 60;
// add the HTTP Keep-Alive header to speed up proxy requests
const opts = {
agent: new https.Agent({
keepAlive: true
}),
timeout: 5000
};
// create express app on port 3000
const app = express();
app.use(Sentry.Handlers.requestHandler());
app.use(morgan('dev'));
app.use(helmet());
const port = process.env.PORT;
const host = process.env.REDIS_URL ? process.env.REDIS_URL : '';
var client = redis.createClient({url: host});
client.connect().then(console.log);
bluebird.promisifyAll(redis);
app.all('/*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/api/getdeparturesbystop', async (req, res) => {
const { stop_id } = req.query;
if (!stop_id) {
return res.status(400).send('invalid');
}
let stringifiedCurrentEntry = await client.get(stop_id);
let resp;
if (stringifiedCurrentEntry) {
// cache hit!
const JSONCurrentEntry = JSON.parse(stringifiedCurrentEntry);
resp = JSONCurrentEntry;
resp.from_cache = true;
} else {
// missing from the cache store, add new entry
try {
resp = await updateGetDeparturesCache(stop_id);
resp.from_cache = false;
} catch (e) {
Sentry.captureException(e);
console.error('REQUEST ERROR');
if (e.response) console.error(e.response.data);
return res.status(408).send({ status: 408, departures: [] });
}
}
res.send(resp);
});
app.get('/api/getstop', async (req, res) => {
const { stop_id } = req.query;
const key = `${stop_id}.stop`;
if (!stop_id) {
return res.status(400).send('invalid');
}
let stringifiedCurrentEntry = await client.get(key);
let resp;
if (stringifiedCurrentEntry) {
// cache hit!
const JSONCurrentEntry = JSON.parse(stringifiedCurrentEntry);
resp = JSONCurrentEntry;
resp.from_cache = true;
} else {
// missing from the cache store, add new entry
try {
resp = await updateGetStopCache(stop_id);
resp.from_cache = false;
} catch (e) {
Sentry.captureException(e);
console.error('REQUEST ERROR');
if (e.response) console.error(e.response.data);
return res.status(408).send({ status: 408, stops: [] });
}
}
res.send(resp);
});
app.get('/api/*', async (req, res) => {
// set the base url
let apiReqUrl = `${API_URI}/${req.params[0]}?key=${CUMTD_API_KEY}`;
for (var key in req.query) {
// if some reason the key is a query param, ignore it
if (key != 'key') {
// iterate over all keys, adding each to the URL
apiReqUrl += `&${key}=${req.query[key]}`;
}
}
try {
const json = (await axios.get(apiReqUrl, opts)).data;
res.send(json);
} catch (e) {
Sentry.captureException(e);
if (e.response) console.error(e.response.data);
res.status(500).send('error');
}
});
app.use(Sentry.Handlers.errorHandler());
const updateGetDeparturesCache = async stop_id => {
// get latest info
let json = (await axios.get(
`${API_URI}/getdeparturesbystop?key=${CUMTD_API_KEY}&stop_id=${stop_id}&pt=${MAX_EXPECTED_MINS_AWAY}`,
opts
)).data;
await client.set(stop_id, JSON.stringify(json), {EX: 30});
return json;
};
const updateGetStopCache = async stop_id => {
// get latest info
let json = (await axios.get(
`${API_URI}/getstop?key=${CUMTD_API_KEY}&stop_id=${stop_id}`,
opts
)).data;
// refresh every 24 hours
await client.set(
`${stop_id}.stop`,
JSON.stringify(json),
'EX',
60 * 60 * 24
);
return json;
};
if (process.env.NODE_ENV !== 'test') {
app.listen(port, () => console.log(`Express app listening on port ${port}!`));
}
module.exports = { app, client };