NeXtMidas makes it very easy to create a web service that responds to HTTP (Hyper Text Transfer Protocol) requests. This section will demonstrate the steps to create your own web service.
NOTE: This section assumes the user is familiar with HTTP and knows some basics about HTTP messages. |
There are two key parts to the web server:
The primitive used to start/manage the server is usually very simple. It provides the interface between the server and the NeXtMidas environment that is running the server.
package nxm.opt.prim; // <-- Your option tree goes in here import nxm.sys.lib.*; import nxm.opt.lib.*; // <-- Your option tree goes in here public class myserver extends Primitive { private MyServer server; // Handle to the server public int open() { int port = 9999; // <-- Get port number from command line Table options = null; // <-- Get options table from command line server = MyServer.startNewServer(M, this, port, options); return NORMAL; } public int process() { int status = NORMAL; if (!server.isRunning()) { status = FINISH; } else { // The server is running in its own thread, so this thread // needs to pause to prevent it from taking up too much CPU. Time.sleep(1.0); } return status; } public int close() { return NORMAL; } }
The library that extends HSource
is where the real work gets done. The
start()
method starts the service, opens the socket, and starts the thread
that will wait for incoming connections. The handleRequest(String,HPage)
method will be called with each incoming request. The handleRequest(String,HPage)
method is the one that does all of the real work. In this example handleRequest
calls processRequest
which does the work of writing out to the HPage
(for any Java experts, the HPage
class just wraps the underlying socket with a
few ease-of-use methods).
package nxm.opt.lib; // <-- Your option tree goes in here import nxm.sys.inc.*; import nxm.sys.lib.*; import nxm.sys.net.*; public class MyServer extends HSource { /** Title of server displayed on the top-level page. */ private static final String SERVER_TITLE = "My server"; /** Directory this service resides in. */ private static final String SERVER_DIR = "myserver"; private HServer hserver; // Handle to the HServer in use. private Midas midas; // Handle to the current Midas context. private Command command; // The command that started the server. private Table options; // Command options. private boolean running; // Is the server running? /** Creates a new instance of the server, but does not start it. @param midas The Midas context to use. @param cmd The command running this server. */ private MyServer(HServer hserver, Midas midas, Command cmd, Table options) { super(SERVER_DIR); this.hserver = hserver; this.midas = midas; this.command = cmd; this.options = options; this.running = true; } /** Tells if the server is running. */ public boolean isRunning() { return running; } /** Starts the server. @param midas The Midas context to use. @param cmd The command running this server. @param port The port to use. @param options Any options for the server. @return The server that has been started. */ public static MyServer startNewServer(Midas midas, Command cmd, int port, Table options) { HServer server = HServer.launch(SERVER_TITLE, port); MyServer myserver = new MyServer(server, midas, cmd, options); server.addSource(myserver); // Connects the server midas.info("MyServer: Server has been started"); return myserver; } public void handleRequest(String uri, HPage hp) { midas.info("MyServer: Got request for "+uri+" from " +hp.getSocket().getRemoteSocketAddress()); try { Table params = getParameters(uri); // Gets any URL parameters processRequest(hp, params); } catch(Exception e) { midas.warning("MyServer: Error while processing request " +"for "+uri+": "+e); midas.printStackTrace(e); } } /** Processes the request. @param hp The HPage to write to. @param params Any parameters from the HTTP request. */ private void processRequest(HPage hp, Table params) { String name = params.getS("NAME"); hp.open(); hp.writeln("<html><body>"); if (name == null) { hp.writeln("<h2>Hello World!</h2>"); } else { hp.writeln("<h2>Hello "+name+"</h2>"); } hp.writeln("</body></html>"); hp.close(); } }
This example can then be tested by using the following URLs in a web browser:
http://localhost:9999/myserver http://localhost:9999/myserver?NAME=Agent+Smith
Note that there is no mechanism for stopping the server in this example. It will be necessary to use Ctrl+C to kill NeXtMidas in order to stop it. This example simply omits the mechanism for stopping the server since such is usually application dependant.
While this example is a simple one it can be easilly expanded to include more complex
tasks that involve processing data and returning different types of data or images.
Please see the HPage
documentation for more information.