U8 hello world


CLI “hello, world” app

Let’s start from writing a simple JavaScript “Hello, world” app for U8. It will be as simple as:

async function main(args) {
    console.log(`Hello, ${(args.length > 0)? args[0] : 'world'}!`);
    return 0;
}

You can launch it as u8 helloworld.js, and it will print out Hello, world!.

And if you launch it as u8 helloworld.js Yourname (substitute your own name as the first argument), it will print out Hello, Yourname!.

Line-by-line explanation

async function main(args) {

The “main” function, just like in a regular application.

The args parameter will contain the arguments passed to it during the launch.

Note the function is async!

    console.log(`Hello, ${(args.length > 0)? args[0] : 'world'}!`);

U8-specific method of logging. Note the convenient ECMA 2015 backtick syntax (template literals) so you can even put some logic into your template strings.

    return 0;

}

The number returned from the main async function becomes the return code of the application.

Alternatively you can return a Promise to wait on (which should provide the actual return code). You may want to read U8 main function and async calls article for more details on that.


“Hello, world” web server

Making an U8 web server is not much more complex either:

import {HttpServer} from 'web'

async function main(args) {
    let httpServer = new HttpServer("0.0.0.0", 8080, platform.hardwareConcurrency);
    httpServer.addRawEndpoint("/hello", async(request) => {
        let nameArg = request.queryParamsMap.get("name");
        let name = (typeof nameArg === "undefined")? "world" : nameArg;
        request.setHeader("Content-Type", "text/html");
        request.setAnswerBody(`Hello, <b>${name}</b>!`);
        request.sendAnswer();
    });
    httpServer.startServer();
    await sleep(10 * 60 * 1000);
}

Launch it as u8 helloworld_http.js, and visit http://localhost:8080/hello endpoint in your browser. It will return a page with “Hello, world!” words on it. And if you pass a name parameter to it, like http://localhost:8080/hello?name=Johnny – the page will contain “Hello, Johnny!” (or the name you’ve passed) instead.

Line-by-line explanation

import {HttpServer} from 'web'

Some special modules (especially Universa-specific ones) are premade in the jslib directory of U8, check Github for more details.

One of them is web, containing the HttpServer class, supporting both raw endpoints (for regular HTTP calls) and such Universa-specific features as “secure endpoints”.

Check out [U8 - importing and exporting symbols from JavaScript files|#151]] article for more details on importing and including the JavaScript files in U8.

async function main(args) {

A “main” function; asynchronous as usual.

    let httpServer = new HttpServer("0.0.0.0", 8080, platform.hardwareConcurrency);

Create the HTTP server, using the class provided by the web module. The first argument is the IP to bind ("0.0.0.0" is an usual metaphor to “bind whenever possible”); the second argument (8080) is the port to listen on, and the third argument is the pool size (let’s set it to the number of the CPU cores).

    httpServer.addRawEndpoint("/hello", async(request) => {

We add just a single endpoint for demo purposes, and it will be /hello one (note not even the / one). You can add more endpoints yourself, if you wish.

The handler of this endpoint will be asynchronous. Async/await is everywhere in U8, and this is what distinguishes it from from Node.js so much.

The handler will receive the request argument, containing the details of the HTTP request.

        let nameArg = request.queryParamsMap.get("name");

Let’s examine the request argument and get a name parameter from it. Note it can be undefined!

        let name = (typeof nameArg == "undefined")? "world" : nameArg;

We don’t want to handle the undefined name. So if no name argument is provided, we will reply with the world word; otherwise the contents of the name argument is used.

        request.setHeader("Content-Type", "text/html");

Let’s start building a reply. The browser will treat (and format if needed) this page as the HTML page. Though there will be very little formatting.

        request.setAnswerBody(`Hello, <b>${name}</b>!`);

Let’s build the reply, putting the words Hello, (and then the name or the world word) and the exclamation sign, as usual. The name (or world) will be HTML-formatted in bold fonts.

        request.sendAnswer();

Sending the reply back,.. and so ends the endpoint handler.

    });

… and so ends the endpoint (/hello) handler.

    httpServer.startServer();

We’ve prepared our HTTP server and made a single endpoint handler. Now just launch it.

    await sleep(10 * 60 * 1000);

}

Interestingly, if we just return from here – our main function will be finished, so the application is closed immediately. And our web server we’ve spent so much time to built, quits immediately too.

So we need to pause somehow. We can “await forever”, have a Promise-returning function which decides when the web server (and the application) should quit; in this example, we just await for 10 minutes and then exit.

This ends our tiny but fully functional web server.