Welcome to the Harris Geospatial product documentation center. Here you will find reference guides, help documents, and product libraries.


Harris Geospatial / Docs Center / Geospatial Services Framework / GSF Tutorial: Custom Request Handler

Geospatial Services Framework

GSF Tutorial: Custom Request Handler

GSF - Tutorial - Custom Request Handler

A request handler is designed to support client access to the server. Most of the default request handlers are designed around providing REST support for submitting jobs, but any communication method could be supported. This tutorial sets up a webpage for a browser client to use. The browser then uses AJAX to communicate with the server.

Create a Custom Request Handler


Create a new folder under the server directory named custom-request-handler. This folder will contain all files created during this tutorial:

Note: As in other tutorials, the full example code blocks are provided here at the bottom of the page.

package.json

Create a file called package.json in the custom-request-handler folder. Add the following contents to the file:

{
  "name": "custom-request-handler",
  "version": "1.0.0",
  "description": "Provides a web client for submitting a job to the server.",
  "main": "handler.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {}
}

This file provides information about the request handler and its dependencies, which, in this case, is quite simple.

handler.js

Create a file called handler.js in the custom-request-handler folder.

Add the following javascript code to the handler.js file. This is the necessary code for the request handler.

The first step for building a custom request handler is defining the class for export.

var express = require('express');
/**
 * CustomRequestHandler
 * Provides an endpoint for serving up a static HTML page for submitting jobs.
 */
function CustomRequestHandler() {
  <!-- TODO fill me in -->
}

A request handler only has one function it needs to implement. The init function is where the request handler is passed references to server objects so it can interact with the server. Place the following code within the CustomRequestHandler function.

  this.init = function(app) {
    // Set up endpoint.
    app.use('/custom/', express.static(__dirname + '/html/'));
  };

this.init = function attaches a new function to the CustomRequestHandler class. The request handler interface is implemented this way.

The app parameter is the express instance for the server. This object can be used to set up any HTTP-based endpoints. However, be careful about name conflicts. If the endpoint here conflicts with another express endpoint, then the load order the request handlers determines which one the system uses. This could potentially be useful in more complex implementations, but this tutorial assumes a unique endpoint.

app.use is an express function for attaching middleware. In this case, the function attaches the express provided static file middleware to the '/custom/' endpoint. This tells express to serve all of the files in the custom-request-handler/html/ folder on the /custom/ endpoint.

__dirname is a reference to the folder containing the current file.

The final line exports the class. The server creates a new instance of this class when loading the modules. Place this code line at the end of the handler.js file, after the CustomRequestHandler function.

  module.exports = CustomRequestHandler;

index.html

It is now time to create the HTML page that to be served up by the new request handler. The purpose of this page is to allow users to define a task with custom parameters and submit that task to the server.

Create a folder within the custom-request-handler folder called html. Within the html folder, create a file named index.html, and open it for edit. The server, by default, serves up any file with the name index.html within this directory.

The HTML header first defines a title for the page, Job Form, using the "title" tag. The "script src" tag specifies the external script file for jQuery, which is needed to use its Ajax functionality.

!<DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Job Form</title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
</head>

The next step is to build the form:

<form id="postJobForm" name="postJobForm">
    <fieldset>
        <legend>Submit a Job</legend>
        Task:<br>
        <input id="Task" size="60" type="text" value="SpectralIndex"><br>
        <br>
        Input Parameters (JSON):<br>
        <textarea cols="60" id="InputParameters" name="inputs" rows="9">
{
    "INPUT_RASTER": {
        "url": "http://localhost:9191/ese/data/qb_boulder_msi",
        "factory": "URLRaster"
    },
    "INDEX": "Normalized Difference Vegetation Index"
}
        </textarea>
        <br>
        <button type="submit">Submit</button>
    </fieldset>
</form>

This form contains three elements: a text field for the task name, a text field for the input parameters in JSON format, and a submit button. In this example, the input task and parameters default to a spectral index task using the Normalized Difference Vegetation Index.

Next, create an HTML division element (div) to be populated after the request is sent:

<h4>Job Status URL:</h4>
<div id="jobStatusURL"></div>

The rest of the code is JavaScript for submitting the form using Ajax. Place the next two functions within the script section of the code.

</script>
    <!-- TODO fill me in -->
</script>
</body>
</html>

The first line attaches a handler to the submit button. The call to event.preventDefault() simply stops the default submission, so the custom code take control. Next, the code extracts the task and input parameter values from the form and parses them into a JavaScript object called params.

    // Attach a submit handler to the form.
    $("#postJobForm").submit(function(event) {
        // Stop form from submitting normally.
        event.preventDefault();
        // Get the task.
        var task = $('#Task').val();
        // Get input parameters from form.
        var params = JSON.parse($('#InputParameters').val());
        // POST request.
        doPost(task, params);
    });

The parameters (params) are then passed into a custom-built function called doPost() that builds the POST request:

    function doPost(task, params) {
        $.ajax({
            type: "POST",
            url: "/ese/services/ENVI/" + task + "/submitJob",
            data: JSON.stringify(params),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(data, textStatus, jqXHR) {
                // Display link to job status endpoint.
                $("#jobStatusURL").empty().append('<a href=/' + data.jobStatusURL + ' target="_blank">/' + data.jobStatusURL + '<\/a>');
            },
            error: function(data) {
            }
        });
    }

Using Ajax, doPost() builds a POST request based on the incoming parameters. Here, the endpoint is submitJob. The POST HTTP Method is used, and the URL is assembled using the task name as specified by the user. The input parameters are set in the data property. The success and error properties define what to do in case of success or failure. The system displays the job status URL in the event of a successful POST request. The user can use this URL to check the job status.

Configure The Server

The last step is to add the new custom-request-handler to the list of request handlers. To do this from a command line, start a command prompt in the GSFxx directory and execute the following command:

node updateConfig.js config.json --arrayadd requestHandlers={\"type\":\"./custom-request-handler\"}

The updateConfig.js script will automatically back up the original config.json file for you.

You may also manually enable the custom-request-handler by editing the config.json as shown below:

  "requestHandlers": [
    ...,
    {
      "type": "./custom-request-handler"
    }
  ],

Restart the server any time this file is changed so it reflects the new configuration.

Using The New Endpoint

Start the server. In a browser, navigate to:

http://<server>:<port>/custom/

For example, if running the server locally with default configurations, the endpoint is found here:

http://localhost:9191/custom/

The newly-created HTML page now displays in the browser window. The user may either accept the defaults or provide their own values for the task and input parameters.

Click the Submit button to submit the job to the server. A link to the job status is now displayed. Clicking on the Job Status URL shows job's status as it executes.

Full Example Code Blocks

Place all of the following files in the custom-request-handler folder and add the provided contents. Remember to Configure the Server before attempting to execute these processes.

package.json

{
  "name": "custom-request-handler",
  "version": "1.0.0",
  "description": "Provides a web client for submitting a job to the server.",
  "main": "handler.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {}
}

handler.js

var express = require('express');
/**
 * CustomRequestHandler
 * Provides an endpoint for serving up a static HTML page for submitting jobs.
 */
function CustomRequestHandler() {
  this.init = function(app) {
    // Set up endpoint.
    app.use('/custom/', require('express').static(__dirname + '/html/'));
  };
}
module.exports = CustomRequestHandler;

index.html

Add the following code to an index.html file within the html subfolder inside the custom-request-handler folder.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Job Form</title>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
</head>
<body>
<form id="postJobForm" name="postJobForm">
    <fieldset>
        <legend>Submit a Job</legend>
        Task:<br>
        <input id="Task" size="60" type="text" value="SpectralIndex"><br>
        <br>
        Input Parameters (JSON):<br>
        <textarea cols="60" id="InputParameters" name="inputs" rows="9">
{
    "INPUT_RASTER": {
        "url": "http://localhost:9191/ese/data/qb_boulder_msi",
        "factory": "URLRaster"
    },
    "INDEX": "Normalized Difference Vegetation Index"
}
        </textarea>
        <br>
        <button type="submit">Submit</button>
    </fieldset>
</form>
<h4>Job Status URL:</h4>
<div id="jobStatusURL"></div>
<script>
    // Attach a submit handler to the form.
    $("#postJobForm").submit(function(event) {
        // Stop form from submitting normally.
        event.preventDefault();
        // Get the task.
        var task = $('#Task').val();
        // Get input parameters from form.
        var params = JSON.parse($('#InputParameters').val());
        // POST request.
        doPost(task, params);
    });
    function doPost(task, params) {
        $.ajax({
            type: "POST",
            url: "/ese/services/ENVI/" + task + "/submitJob",
            data: JSON.stringify(params),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(data, textStatus, jqXHR) {
                // Display link to job status endpoint.
                $("#jobStatusURL").empty().append('<a href=/' + data.jobStatusURL + ' target="_blank">/' + data.jobStatusURL + '<\/a>');
            },
            error: function(data) {
            }
        });
    }
</script>
</body>
</html>



© 2017 Exelis Visual Information Solutions, Inc. |  Legal
My Account    |    Buy    |    Contact Us