-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathserver.js
More file actions
113 lines (102 loc) · 2.73 KB
/
server.js
File metadata and controls
113 lines (102 loc) · 2.73 KB
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
"use strict"
let redis = require("redis")
let url = require("url")
let typeset = require("./typeset")
class Server {
constructor(redisPort, redisHost) {
this.ts = typeset
this.useRedis = !!(redisHost && redisPort)
if (this.useRedis) {
this.redisCli = redis.createClient(redisPort, redisHost)
}
}
handleRequest(req, res) {
if (req.method !== "GET") {
this.sendError(res, 405, "Method not allowed.")
return
}
let uri = url.parse(req.url, true)
let type = uri.pathname.replace(/^\/+|\/+$/g, "")
if (type !== "svg" && type !== "mml") {
this.sendError(res, 404, "Not Found")
return
}
let tex = uri.query.tex
if (!tex) {
this.sendBadRequest(res, "no LaTeX provided.")
return
}
const scale = parseFloat(uri.query.scale || 1)
if (!scale) {
this.sendBadRequest(res, "invalid scale provided.")
return
}
if (req.headers["if-modified-since"]) {
this.sendNotModified(res)
return
}
this.sendCachedResponse(res, type, tex, scale)
}
sendBadRequest(res, reason) {
this.sendError(res, 400, "Bad request: " + reason)
}
sendError(res, code, message) {
res.writeHead(code, { "Content-Type": "text/plain" })
res.end(message)
}
sendNotModified(res) {
res.writeHead(304)
res.end()
}
// account for bytesize of unicode characters like '£'
getByteCount(str) {
return encodeURI(str).split(/%..|./).length - 1
}
sendResponse(res, type, body, scale = 1) {
let headers = {
"Content-Type":
type === "svg" ? "image/svg+xml" : "application/mathml+xml",
}
headers["content-length"] = this.getByteCount(body)
res.writeHead(200, headers)
res.end(body)
}
sendTypesetResponse(res, type, tex, scale = 1) {
this.ts({ tex, scale }, (err, data) => {
if (err) {
this.sendBadRequest(res, err.join("\n"))
return
}
this.sendResponse(res, type, data[type], scale)
if (this.useRedis) {
this.redisCli.mset(
"mml:" + tex,
data["mml"],
"svg:" + tex + ":" + scale,
data["svg"]
)
}
})
}
sendCachedResponse(res, type, tex, scale = 1) {
if (this.useRedis) {
let key = type + ":" + tex
if (type === 'svg') key = `${key}:${scale}`
this.redisCli.get(key, (err, reply) => {
if (err) {
console.log(err)
this.sendTypesetResponse(res, type, tex, scale)
return
}
if (!reply) {
this.sendTypesetResponse(res, type, tex, scale)
return
}
this.sendResponse(res, type, reply, scale)
})
} else {
this.sendTypesetResponse(res, type, tex, scale)
}
}
}
module.exports = Server