Creating the application server
Now that our file server is serving our page, we are going to shift our focus to the application server.
For our application, we will wrap our functionality into a class called Spawner
. We recommend reviewing the Express documentation about Routing before proceeding.
Let’s create our Spawner
class by adding the following code to spawner.js:
// Add Tutorial Code Here
const express = require('express');
class Spawner {
constructor(licenseFile, executablePath, modelDirectory, expressApp) {
this.licenseFile = licenseFile;
this.executablePath = executablePath;
this.modelDirectory = modelDirectory;
this.expressApp = expressApp;
this.serverPort = null;
}
start(port) {
this.serverPort = port;
this.expressApp.post("/spawn", this.spawnViewer.bind(this));
this.expressApp.listen(this.serverPort);
}
spawnViewer(req, res) {
res.status(200).json({result: "spawn viewer!"});
}
}
module.exports = { Spawner }
Right now, this class does not do anything useful. However, we will be adding functionality to it throughout the tutorial. The class wraps an Express application that is passed to the constructor. When the start method is called, a simple POST route to the /spawn endpoint is added, and the Express server is started.
Now that we have our Spawner
class defined, add the following code to the top of the server.js file under the require statement for the paths file:
const { Spawner } = require("./spawner");
Under the code for creating the file server, we will create and start a new Spawner
:
// create spawning server
const spawningServer = express();
const spawner = new Spawner(paths.licenseFile, paths.executablePath, paths.modelDirectory, spawningServer);
spawner.start(8082);
This code creates the Spawner
object using the values we defined in the paths.js file, and passes in a new Express server as a parameter. Once the server starts, it will be listening on port 8082 for connections. At this point, if we run npm start
both our file and application server will start up, ready to work.
Note
In a production environment, you would generally want to separate static file serving from web application logic, but for the sake of simplicity for this tutorial we include them both in the same context.
To test that everything is wired up, we will add some skeleton code to our front end for communicating with the application server. Open server_tutorial/public/index.html and add the following code in the empty <script>
tag contained in the header:
// Add Tutorial Code Here
async function createNewViewer() {
let data = await $.ajax({
url: "http://localhost:8082/spawn",
type:"POST",
data: JSON.stringify({rendererType: $("#renderer-type").val()}),
dataType:"json",
contentType:"application/json",
});
console.log(data);
}
The index.html page is already pre-wired to call this method when the button is clicked. When you load the index page and click the button you would see an error similar to:
The request is being blocked due to CORS. This can be solved by adding some Express configurations that instruct the server to allow connections from our front-end server. In spawner.js, add the following code to the Spawner.start
method before binding the /spawn route:
this.expressApp.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers");
next();
});
This code installs an Express middleware function which adds the proper headers to enable the communication from the front-end to the Spawner
server.
Note
For the tutorial, we are allowing requests from any origin. In a production environment, you will want to restrict this to trusted origins that are under your control.
If you restart the Node.js application and now click the “Create New Viewer” button, you should see a message similar to the following in your console:
With that final step complete, communication has been established between our front-end and back-end. The next section will focus on adding functionality to our Spawner
class for creating Stream Cache Servers.