-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
72 lines (56 loc) · 1.78 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
#!/usr/bin/env node
import {readFileSync} from 'node:fs'
import process from 'node:process'
import express from 'express'
import cors from 'cors'
import morgan from 'morgan'
import Keyv from 'keyv'
import {load as loadYamlFile} from 'js-yaml'
import HttpResolver from './lib/resolvers/http.js'
const ONE_HOUR = 60 * 60
const ONE_DAY = 24 * ONE_HOUR
const EXPIRES_DURATION = 7 * ONE_DAY
const app = express()
const cache = new Keyv('sqlite://cache.sqlite')
app.disable('x-powered-by')
app.use(cors({origin: true}))
if (process.env.NODE_ENV !== 'production') {
app.use(morgan('dev'))
}
const tiles = loadYamlFile(readFileSync('./tiles.yml'))
function w(handler) {
return async (req, res, next) => {
try {
await handler(req, res, next)
} catch (error) {
next(error)
}
}
}
for (const tileService of tiles) {
app.use(`/${tileService.name}/tiles`, (req, res, next) => {
res.sendTile = tileData => {
res
.set('cache-control', `public, max-age=${EXPIRES_DURATION}`)
.set('expires', new Date(Date.now() + (EXPIRES_DURATION * 1000)).toUTCString())
.type(tileService.imageType)
.send(tileData)
}
next()
})
app.get(`/${tileService.name}/tiles/:z/:x/:y`, w(async (req, res) => {
const {z, x, y} = req.params
const key = `${tileService.name}-${z}-${x}-${y}`
const cachedTile = await cache.get(key)
if (cachedTile) {
return res.set('X-Proxy-Cache', 'HIT').sendTile(cachedTile.data)
}
const resolver = new HttpResolver(tileService.resolver.url, tileService.resolver.headers || {})
const tile = await resolver.getTile(z, x, y)
cache.set(key, tile).catch(error => {
console.error(error)
})
res.set('X-Proxy-Cache', 'MISS').sendTile(tile.data)
}))
}
app.listen(process.env.PORT || 5000)