forked from software-tools-books/js4ds
-
Notifications
You must be signed in to change notification settings - Fork 0
/
extensible.tex
67 lines (53 loc) · 1.93 KB
/
extensible.tex
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
\chapter{Extensible Servers}\label{s:extensible}
Suppose we want to extend the server from \chapref{s:server} in some way.
We could edit the source file and add some more URL handlers,
or we could have it load JavaScript dynamically and run that.
\begin{minted}{js}
const express = require('express')
const PORT = 3418
// Main server object.
const app = express()
// Handle all requests.
app.use((req, res, next) => {
if (req.url.endsWith('.js')) {
const libName = './'.concat(req.url.slice(0, -3))
const dynamic = require(libName)
const data = dynamic.page()
res.status(200).send(data)
}
else {
res.status(404).send(
`<html><body><p>"${req.url}" not found</p></body></html>`)
}
})
app.listen(PORT, () => { console.log(`listening on port ${PORT}...`) })
\end{minted}
This simple server checks whether the path specified in the URL ends with \texttt{.js}.
If so,
it constructs something that looks like the name of a library by stripping off the \texttt{.js}
and prefixing the stem with \texttt{./},
then uses \texttt{require} to load that file.
Assuming the load is successful,
it then calls the \texttt{page} function defined in that file.
We can create a very simple plugin like this:
\begin{minted}{js}
function page() {
return ('<html><body><h1>Plugin Content</h1></body></html>');
}
module.exports = {
page: page
}
\end{minted}
If we run the server:
\begin{minted}{shell}
$ node src/extensible/dynamic.js
\end{minted}
\noindent
and then go to \texttt{http://localhost:4000/plugin.js},
we get back a page containing the title ``Plugin Content''.
This is an example of a very powerful technique.
Rather than building everything into one program,
we can provide a \gref{g:protocol}{protocol} for plugins
so that people can add new functionality without rewriting what's already there.
Each plugin must have an \gref{g:entry-point}{entry point} like the function \texttt{page}
so that the framework knows where to start.