create viewcounter
This commit is contained in:
parent
9d2eb0906f
commit
8f3f92d82b
|
@ -1,3 +1,6 @@
|
|||
# view count
|
||||
.count.json
|
||||
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
|
@ -129,4 +132,3 @@ dist
|
|||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"port": 8001,
|
||||
"path": "/viewcounter",
|
||||
"site": "zvava.org",
|
||||
"db": ".count.json",
|
||||
"saveTimeout": 5000
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
import * as fs from "fs"
|
||||
import * as http from "http"
|
||||
import { request } from "https"
|
||||
|
||||
// read configuration
|
||||
let config = readJson("conf.json", {
|
||||
port: 8001,
|
||||
path: "/viewcounter",
|
||||
site: "zvava.org",
|
||||
db: ".count.json",
|
||||
saveTimeout: 5000,
|
||||
})
|
||||
// read existing view count
|
||||
let count = readJson(config.db)
|
||||
// store the save timeout
|
||||
let saveTimeout
|
||||
|
||||
let server = new http.Server((request, response) => {
|
||||
try {
|
||||
if (request.url != config.path)
|
||||
return close(response, 404)
|
||||
|
||||
switch (request.method) {
|
||||
case "GET":
|
||||
close(response, 200, JSON.stringify(count))
|
||||
break
|
||||
|
||||
case "POST":
|
||||
const chunks = []
|
||||
request.on("data", chunk => chunks.push(chunk))
|
||||
request.on("end", async () => {
|
||||
let page = Buffer.concat(chunks).toString()
|
||||
|
||||
// check if page is a valid url
|
||||
if (/\/[a-zA-Z0-9_-]+.html/.test(page) && await validateUrl(page)) {
|
||||
count[page]++
|
||||
saveCount()
|
||||
close(response, 200, "counted page view", { views: count[page] })
|
||||
} else {
|
||||
close(response, 300, "invalid url provided")
|
||||
}
|
||||
})
|
||||
break
|
||||
|
||||
default: resolve(close(response))
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
|
||||
server.listen(config.port)
|
||||
|
||||
function saveCount() {
|
||||
// if a timeout
|
||||
saveTimeout && clearTimeout(saveTimeout)
|
||||
saveTimeout = setTimeout(() => {
|
||||
fs.writeFile(config.db, JSON.stringify(count), (err) =>
|
||||
err && console.error(err))
|
||||
}, config.saveTimeout)
|
||||
}
|
||||
|
||||
// read file, if it exists return it as an object, otherwise return a default object
|
||||
function readJson(file, defaultJson = {}) {
|
||||
try { return JSON.parse(fs.readFileSync(file, "utf-8")) } catch {}
|
||||
|
||||
return defaultJson
|
||||
}
|
||||
|
||||
// helper function to close an incoming http request
|
||||
function close(res, code = 300, message = "", extraData = {}) {
|
||||
res.setHeader("Content-type", "application/json")
|
||||
res.writeHead(code)
|
||||
res.end(JSON.stringify({
|
||||
code,
|
||||
message: message || code.toString(),
|
||||
...extraData
|
||||
}))
|
||||
}
|
||||
|
||||
// ping the target site and ensure that the url exists
|
||||
function validateUrl(url) {
|
||||
console.log(url)
|
||||
return new Promise((resolve) => {
|
||||
request({
|
||||
method: "HEAD",
|
||||
host: config.site,
|
||||
path: url,
|
||||
}, (response) => {
|
||||
console.log(response.statusCode, response.headers)
|
||||
resolve(response.statusCode == 200)
|
||||
}).end()
|
||||
})
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"main": "index.js",
|
||||
"type": "module"
|
||||
}
|
Loading…
Reference in New Issue