|
@@ -5,15 +5,15 @@ import { maxQuery, maxRows } from './config.js'
|
|
|
const { DATABASE } = process.env
|
|
|
const db = DATABASE ? await import(`./database/${DATABASE}.js`) : null
|
|
|
|
|
|
-const generateRandomNumber = () => Math.ceil(Math.random() * maxRows)
|
|
|
+const generateRandomNumber = () => Math.floor(Math.random() * maxRows) + 1
|
|
|
|
|
|
-const parseQueries = (i) => Math.min(Math.max(parseInt(i, 10) || 1, 1), maxQuery)
|
|
|
+const parseQueries = (i) => Math.min(parseInt(i) || 1, maxQuery)
|
|
|
|
|
|
const escapeHTMLRules = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' }
|
|
|
|
|
|
const unsafeHTMLMatcher = /[&<>"'\/]/g
|
|
|
|
|
|
-const escapeHTMLCode = (text) => text ? text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; }) : ''
|
|
|
+const escapeHTMLCode = (text) => unsafeHTMLMatcher.test(text) ? text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; }) : text
|
|
|
|
|
|
const cache = new LRUCache({
|
|
|
max: maxRows
|
|
@@ -24,15 +24,11 @@ const app = new Server()
|
|
|
// use middleware to add `Server` into response header
|
|
|
app.use((_request, response, next) => {
|
|
|
response.header('Server', 'hyperexpress')
|
|
|
- next()
|
|
|
+ return next()
|
|
|
})
|
|
|
|
|
|
app.get('/plaintext', (_request, response) => {
|
|
|
- response.atomic(() => {
|
|
|
- response
|
|
|
- .type('text')
|
|
|
- .send('Hello, World!')
|
|
|
- })
|
|
|
+ response.type('text').send('Hello, World!')
|
|
|
})
|
|
|
|
|
|
app.get('/json', (_request, response) => {
|
|
@@ -40,17 +36,10 @@ app.get('/json', (_request, response) => {
|
|
|
})
|
|
|
|
|
|
if (db) {
|
|
|
- // populate cache
|
|
|
- (async () => {
|
|
|
- const worlds = await db.getAllWorlds()
|
|
|
- for (let i = 0; i < worlds.length; i++) {
|
|
|
- cache.set(worlds[i].id, worlds[i])
|
|
|
- }
|
|
|
- })()
|
|
|
-
|
|
|
app.get('/db', async (_request, response) => {
|
|
|
try {
|
|
|
const world = await db.find(generateRandomNumber())
|
|
|
+
|
|
|
response.json(world)
|
|
|
} catch (error) {
|
|
|
throw error
|
|
@@ -60,13 +49,14 @@ if (db) {
|
|
|
app.get('/queries', async (request, response) => {
|
|
|
try {
|
|
|
const queries = parseQueries(request.query.queries)
|
|
|
- const worldPromises = []
|
|
|
+ const worldPromises = new Array(queries)
|
|
|
|
|
|
for (let i = 0; i < queries; i++) {
|
|
|
- worldPromises.push(db.find(generateRandomNumber()))
|
|
|
+ worldPromises[i] = db.find(generateRandomNumber())
|
|
|
}
|
|
|
|
|
|
- const worlds = await Promise.all(worldPromises)
|
|
|
+ const worlds = await Promise.all(worldPromises);
|
|
|
+
|
|
|
response.json(worlds)
|
|
|
} catch (error) {
|
|
|
throw error
|
|
@@ -76,20 +66,22 @@ if (db) {
|
|
|
app.get('/updates', async (request, response) => {
|
|
|
try {
|
|
|
const queries = parseQueries(request.query.queries)
|
|
|
- const worldPromises = []
|
|
|
+ const worldPromises = new Array(queries)
|
|
|
|
|
|
for (let i = 0; i < queries; i++) {
|
|
|
- worldPromises.push(db.find(generateRandomNumber()))
|
|
|
+ worldPromises[i] = db.find(generateRandomNumber())
|
|
|
}
|
|
|
|
|
|
const worlds = await Promise.all(worldPromises)
|
|
|
|
|
|
- const updatedWorlds = await Promise.all(worlds.map(async (world) => {
|
|
|
- world.randomNumber = generateRandomNumber()
|
|
|
- await db.update(world)
|
|
|
- return world
|
|
|
- }))
|
|
|
- response.json(updatedWorlds)
|
|
|
+ for (let i = 0; i < queries; i++) {
|
|
|
+ worlds[i].randomNumber = generateRandomNumber()
|
|
|
+ worldPromises[i] = db.update(worlds[i])
|
|
|
+ }
|
|
|
+
|
|
|
+ await Promise.all(worldPromises)
|
|
|
+
|
|
|
+ response.json(worlds)
|
|
|
} catch (error) {
|
|
|
throw error
|
|
|
}
|
|
@@ -101,27 +93,33 @@ if (db) {
|
|
|
|
|
|
fortunes.push({ id: 0, message: 'Additional fortune added at request time.' })
|
|
|
|
|
|
- fortunes.sort((a, b) => a.message.localeCompare(b.message))
|
|
|
+ fortunes.sort((a, b) => (a.message < b.message) ? -1 : 1)
|
|
|
+
|
|
|
+ const n = fortunes.length
|
|
|
|
|
|
- let i = 0, html = '<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>'
|
|
|
- for (; i < fortunes.length; i++) html += `<tr><td>${fortunes[i].id}</td><td>${escapeHTMLCode(fortunes[i].message)}</td></tr>`
|
|
|
- html += '</table></body></html>'
|
|
|
+ let i = 0, html = ''
|
|
|
+ for (; i < n; i++) html += `<tr><td>${fortunes[i].id}</td><td>${escapeHTMLCode(fortunes[i].message)}</td></tr>`
|
|
|
|
|
|
- response.atomic(() => {
|
|
|
- response
|
|
|
- // .type('html')
|
|
|
- .header('Content-Type', 'text/html; charset=utf-8')
|
|
|
- .send(html)
|
|
|
- })
|
|
|
+ response
|
|
|
+ .header('Content-Type', 'text/html; charset=utf-8')
|
|
|
+ .send(`<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>${html}</table></body></html>`)
|
|
|
} catch (error) {
|
|
|
throw error
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+ let isCachePopulated = false
|
|
|
app.get('/cached-worlds', async (request, response) => {
|
|
|
try {
|
|
|
+ if (!isCachePopulated) {
|
|
|
+ const worlds = await db.getAllWorlds()
|
|
|
+ for (let i = 0; i < worlds.length; i++) {
|
|
|
+ cache.set(worlds[i].id, worlds[i])
|
|
|
+ }
|
|
|
+ isCachePopulated = true
|
|
|
+ }
|
|
|
const count = parseQueries(request.query.count)
|
|
|
- const worlds = []
|
|
|
+ const worlds = new Array(count)
|
|
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
|
worlds[i] = cache.get(generateRandomNumber())
|