This file describes all of the features of tinyServ.
This is an example of a minimal setup:
import * as app from './http.js'
app.onGet('/', async (req, res) => {
res.render('index.html', {name: 'LiveOverflow'})
})
app.onPost('/submit', async (req, res) => {
let data = await req.getPostData()
res.render('index.html', {name: data.name})
})
let server = await app.start()Let's look at the example in more detail.
app.onGet('/', async (req, res) => {
res.render('index.html', {name: 'LiveOverflow'})
})app.onGet registers the handler for the GET request to this route. The handler needs to be an async function to be able to await data.
res.render renders the page and closes the connection.
app.onPost('/submit', async (req, res) => {
let data = await req.getPostData()
res.render('index.html', {name: data.name})
})app.onPost registers a POST route.
You can get the POST data with req.getPostData. That is an async function so you have to await it.
let server = await app.start()app.start starts the server and returns the http server instance.
You can pass it the port number you want (default 80):
let server = await app.start(3000)You can start the server with options, like this:
let server = await app.start(3000, {
flattenData: true,
escapeRender: true,
whitelistPaths: true,
maxRequestsPerSecond: 20,
DDOStimeoutMinutes: 5
})These are the defaults for the options.
whitelistPaths is explained in its own section after Security measures.
The other options are security options. They are explained in detail in the Security measures section below.
In this part we will look at some other examples. The following code snippets can be inserted right before
let server = await app.start()You can read cookies using req.getCookie.
app.onGet('/fromCookie', async (req, res) => {
nameCookie = await req.getCookie('name')
res.render('index.html', {name: nameCookie})
})You can also set cookies using res.setCookie.
app.onPost('/submitCookie', async (req, res) => {
let data = await req.getPostData()
res.setCookie('name', data.name)
res.render('index.html', {name: data.name})
})Redirecting is simply done with res.redirect.
app.onGet('/invalid', async (req, res) => {
res.redirect('/')
})You have already seen an example of how to render a simple page. The code looks like this:
app.onGet('/', async (req, res) => {
res.render('index.html', {name: 'LiveOverflow'})
})The file index.html looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome, {{name}}</h1>
<p>This is the home page</p>
<form method="post" action="submit">
<input type="text" name="name" placeholder="Enter your name">
<input type="submit" value="Submit">
</form>
</body>
</html>As you can see, the key between the curly brackets ( here {{name}} ) will be replaced with the matching value of the object passed to render.
You can do more with the render function.
By default, the render function will render files from /public/. But if you call it like this
res.render('about.html', true)it will render a file from the /public/static/ directory.
You can also pass it a different status code:
res.render('index.html', {name: 'LiveOverflow'}, 204)By default, the render function will escape all non-alphanumerical characters in the input. To prevent that, call it like this:
res.render('index.html', {name: '<b>LiveOverflow</b>', noEscape: true})Settings mean ServerOptions passed when starting the server.
As you saw above, the render function automatically escapes characters. This can be disabled by setting escapeRender to false. You can still escape the data with
app.objEscapeHTML(data)you can also escape a single string using
app.escapeHTML(string)Query data and POST body data is automatically flattened. If the data contains arrays, it is recursive replaced with its first element. Setting flattenData to false in the ServerOptions will disable this behavior. You can flatten data yourself by using
app.flatten(data)and flatten arrays using
app.arrToFlat(array)This server contains automatic DDOS protection. If a user makes more requests per second than allowed, they are banned for a certain amount of time. The number of requests is customizable through the option maxRequestsPerSecond, the ban time in minutes is set with DDOStimeoutMinutes.
WhitelistPaths is a feature that speeds up 404 request handling. It works by caching all files in the /public/ directory when the server starts. When the server is running it only checks if a page renderer is already available, and does not try to generate a new one, slowing the server down with file system operations. This might be useful to reduce the impact of the first load of a page after a server start. A downside is the increased startup time as the server traverses all directories in the /public/ directory and generates renderers on startup.
When requested a url like /about , the server first looks for a handler for '/about' set by the user. If the handler is not found, it looks for a handler for 'default'.
If that also is not present, the server tries to render the file itself. It looks in the /public/static/ directory to find a file with the same name. The server changes / into /index.html and appends .html to paths with no extension.
If the file doesn't exist, it tries to call the handler for 'err404'. If the handler is not found, it tries to render /public/static/404.html . If that file doesn't exist, it simply returns a 404 error code and closes the connection.
In short, the algorithm looks like this:
- Call handler for
${path} - Call handler for
'default' - If
${path}is/:${path}=/index.html - If
${path}does not include a'.':${path}+=.html - Render
/public/static/${path} - Call handler for
'err404' - Render
/public/static/404.html - Return 404 error code and close the connection