-
-
Notifications
You must be signed in to change notification settings - Fork 11
/
api.js
143 lines (126 loc) · 4.11 KB
/
api.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
// todo: use import assertions once they're supported by Node.js & ESLint
// https://github.com/tc39/proposal-import-assertions
import {createRequire} from 'node:module'
const require = createRequire(import.meta.url)
import {dirname, join as pathJoin} from 'node:path'
import {fileURLToPath} from 'node:url'
import {
createDbHafas as createHafas,
defaults as dbHafasDefaults,
} from 'db-hafas'
import {createWriteStream} from 'node:fs'
import {createHafasRestApi} from 'hafas-rest-api'
import createHealthCheck from 'hafas-client-health-check'
import Redis from 'ioredis'
import {createCachedHafasClient} from 'cached-hafas-client'
import {createRedisStore} from 'cached-hafas-client/stores/redis.js'
import serveStatic from 'serve-static'
import {parseBoolean, parseInteger} from 'hafas-rest-api/lib/parse.js'
import {loyaltyCardParser} from './lib/loyalty-cards.js'
import {route as stations} from './routes/stations.js'
import {route as station} from './routes/station.js'
const pkg = require('./package.json')
const __dirname = dirname(fileURLToPath(import.meta.url))
const docsRoot = pathJoin(__dirname, 'docs')
const berlinHbf = '8011160'
const customDbProfile = {
...dbHafasDefaults.profile,
}
// todo: DRY env var check with localaddress-agent/random-from-env.js
// Currently, this is impossible: localaddress-agent is an optional dependencies, so we rely on it to check the env var.
if (process.env.RANDOM_LOCAL_ADDRESSES_RANGE) {
const {randomLocalAddressAgent} = await import('localaddress-agent/random-from-env.js')
customDbProfile.transformReq = (_, req) => {
req.agent = randomLocalAddressAgent
return req
}
}
if (process.env.HAFAS_REQ_RES_LOG_FILE) {
const hafasLogPath = process.env.HAFAS_REQ_RES_LOG_FILE
const hafasLog = createWriteStream(hafasLogPath, {flags: 'a'}) // append-only
hafasLog.on('error', (err) => console.error('hafasLog error', err))
customDbProfile.logRequest = (ctx, req, reqId) => {
console.error(reqId, 'req', req.body + '') // todo: remove
hafasLog.write(JSON.stringify([reqId, 'req', req.body + '']) + '\n')
}
customDbProfile.logResponse = (ctx, res, body, reqId) => {
console.error(reqId, 'res', body + '') // todo: remove
hafasLog.write(JSON.stringify([reqId, 'res', body + '']) + '\n')
}
}
// todo: use process.env.HAFAS_USER_AGENT if defined
let hafas = createHafas(pkg.name, {
profile: customDbProfile,
})
let healthCheck = createHealthCheck(hafas, berlinHbf)
if (process.env.REDIS_URL) {
const redis = new Redis(process.env.REDIS_URL || null)
hafas = createCachedHafasClient(hafas, createRedisStore(redis), {
cachePeriods: {
locations: 6 * 60 * 60 * 1000, // 6h
},
})
const checkHafas = healthCheck
const checkRedis = () => new Promise((resolve, reject) => {
setTimeout(reject, 1000, new Error('didn\'t receive a PONG'))
redis.ping().then(
res => resolve(res === 'PONG'),
reject,
)
})
healthCheck = async () => (
(await checkHafas()) === true &&
(await checkRedis()) === true
)
}
const mapRouteParsers = (route, parsers) => {
if (route !== 'journeys') return parsers
return {
...parsers,
loyaltyCard: loyaltyCardParser,
firstClass: {
description: 'Search for first-class options?',
type: 'boolean',
default: 'false',
parse: parseBoolean,
},
age: {
description: 'Age of traveller',
type: 'integer',
defaultStr: '*adult*',
parse: parseInteger
},
}
}
const modifyRoutes = (routes, hafas, config) => {
routes['/stations/:id'] = station
routes['/stations'] = stations
return routes
}
const config = {
hostname: process.env.HOSTNAME || 'localhost',
port: process.env.PORT ? parseInt(process.env.PORT) : 3000,
name: pkg.name,
description: pkg.description,
homepage: pkg.homepage,
version: pkg.version,
docsLink: 'https://github.com/derhuerst/db-rest/blob/6/docs/readme.md',
openapiSpec: true,
logging: true,
aboutPage: false,
etags: 'strong',
csp: `default-src 'none' style-src 'self' 'unsafe-inline' img-src https:`,
healthCheck,
mapRouteParsers,
modifyRoutes,
}
const api = await createHafasRestApi(hafas, config, (api) => {
api.use('/', serveStatic(docsRoot, {
extensions: ['html', 'htm'],
}))
})
export {
hafas,
config,
api,
}