Goals
After this tutorial, you should be able to
- Install the GEhttpd server
- Configure the server settings
- Create URL routes to map to GAUSS procs
- Rules for passing data to GAUSS
- Test URLs from separate clients
Install
- Prerequisite: The GAUSS Engine must first be installed. Note the installation path for configuring the server settings. The default paths will be
C:\mteng19
for Windows and~/mteng19
for non-Windows installations. - Unzip gehttpd.zip to a directory of your choice.
TODO: Add Windows/Linux service scripts
Configure
Open gehttpd/etc/gehttpd.ini
in an editor of your choice that will maintain the correct line endings (ie do not use Notepad). In most cases the default settings will suffice, but can be modified. Only basic settings will be covered here.
Fields are described in comments.
- Edit host / port settings. Default settings should suffice.
[listener]; uncomment the below line to specify a specific address to bind to.; the default is to bind to all available IPv4/IPv6 network interfaces;host=127.0.0.1; the default port is 5050. since this is most beneficial to run as; an application server, not running on port 80/443 allows a separate; traditional web server such as apache or nginx to run alongside it.port=5050
- Edit GAUSS routes
[gehttpd]; specify the GAUSS Engine installation path.home=C:/mteng19; specify the GAUSS source files to parse. multiple files are; separated with the pipe '|' character and the path is relative; to the root of the gehttpd directoryfilenames=test/sample.e|test/echo.e; setting persistent workspace to 1 enables session handling.; each individual client will have their own GAUSS workspace; stored in a session, meaning subsequent requests can access; or modify global symbols from previous requests.; disabling this option means a clean workspace will be used; with each new requestpersistentWorkspace=0
- (Optional) Edit logging location.
[logging]; default log location is gehttpd/logs/gehttpd.log; comment out the below line to have all activity logged to; the consolefileName=../logs/gehttpd.log
Create URL routes to map to GAUSS procs
These files are to be included in the filenames
key of the gehttpd.ini
configuration file.
A URL route to GAUSS proc mapping consists of 3 steps:
- Include the
gehttpdroutes.src
file. This is only necessary once per source file. - Define the GAUSS proc
- Use the
route
function to tell gehttpd how to handle the proc and associated URL path.
The 'route' function explained
/* **> route ** ** Purpose: Register a URL route with the gehttpd web server. ** ** Format: route(url, procname, args); ** ** Input: url string, the relative path used to access the GAUSS proc ** from a client. Always starts with a forward-slash '/'. ** ** Can have multiple forms: ** 1. "/sample" : The most traditional URL style, where all ** arguments (or none) are passed to the web server as GET ** or POST parameters. ** ** 2. "/sample/<foo>/<bar>" : A REST style URL. Arguments are ** specified directly in the URL surrounded by brackets. ** These argument names must match up to the argument names ** in the third argument of the 'route' method. ** ** NOTE: The order does not have to be the same as the order ** specifed in 'args'. ** ** procname string, the name of the GAUSS proc to execute when the ** specified URL is accessed. ** ** args string, ordered comma-delimited list of arguments that the ** proc accepts. These argument names must match the web request ** parameter names exactly. This argument determines the correct ** ordering when calling the GAUSS proc. ** ** NOTE: Prefixing an argument with the '$' character denotes that ** this argument will always be converted to a string when ** the GAUSS proc is executed. ** */ proc route(url, procname, args);
Example 1
The following example will cover the most basic proc possible. A simple echo proc that returns the argument passed in.
// Step 1: Include the gehttpdroutes.src file #include gehttpdroutes.src // Step 2: Define the GAUSS proc proc (1) = echo(v); retp(v); endp; // Step 3: Instruct gehttpd how to handle this proc. route("/echo", "echo", "v");
Testing this example
http://localhost:5050/echo?v=50
Example 2
This example will show how to force certain proc arguments to be strings. This can be helpful in cases where the client passes a numeric parameter but the GAUSS proc argument expects a string.
#include gehttpdroutes.src proc (1) = hello(name); retp("Hello " $+ name); endp; // Two separate styles route("/hello", "hello", "$name"); // note that the URL does not have to match the name of the proc route("/say_hi_to/<name>", "hello", "$name");
Testing this example
Example 3
This example will show to pass multiple arguments into a proc using both traditional and REST style paths.
#include gehttpdroutes.src proc (1) = subtract(a, b); retp(a-b); endp; route("/minus", "subtract", "a,b"); // this REST style shows how multiple path separators can be used // NOTE that we can also specify the REST arguments in any order we choose as // long as we correctly specify the order correctly in the third argument. // (ie 'b' and 'a' could be swapped in the path) route("/<a>/minus/<b>", "subtract", "a,b");
Testing this example
- http://localhost:5050/minus?a=10&b=5
- http://localhost:5050/minus?b=5&a=10
- http://localhost:5050/10/minus/5
Rules for passing data to GAUSS
The following rules describe acceptable ways to pass data via GET or POST requests to GAUSS. Python will be used to illustrate the rules.
If submitting as a POST request, then the entire POST body can also be JSON encoded. This is most useful in the context of JSON-encoding an entire dictionary as opposed to each argument individually.
Scalars / Strings
Scalar arguments can be set directly (do not have to be JSON-encoded with type)
# GET r = requests.get('http://localhost:5050/minus', params={'a': 50, 'b': 25})
# GET r = requests.get('http://localhost:5050/echo', params={'v': 'hello world'})
# POST - not necessary to use json.dumps when passing scalars only r = requests.post('http://localhost:5050/minus', data={'a': 50, 'b': 25})
Matrices and string arrays
Matrices or string arrays are required to be JSON-encoded. Please note the json.dumps
args = { 'a': json.dumps({ 'type': 6, 'rows': 2, 'cols': 2, 'data': [1, 2, 3, 4] }), 'b': 1 } # GET r = requests.get('http://localhost:5050/minus', params=args) #POST r = requests.post('http://localhost:5050/minus', data=args)
String arrays are dealt with the same as matrices.
args = { 'v': json.dumps({ 'type': 13, 'data': ["one", "two", "three", "four"] }) } # GET r = requests.get('http://localhost:5050/echo', params=args) #POST r = requests.post('http://localhost:5050/echo', data=args)
Test URLs from separate clients
The tests below are based off the previous examples. More examples are located in the gehttpd/test/test.py
file.
Python
The following Python tests make use of the requests
package. This can be installed via pip install requests
-
Test the
echo
proc with a numberimport requestsimport jsonr = requests.get('http://localhost:5050/echo', params={'v': 5})# the response will by default be json and parsable as such# {"success":true,"results":[{"type":6,"rows":1,"cols":1,"data":[5.0]}]}print("Echo returned {}".format(json.loads(r.text)["results"][0]["data"][0])) -
Test the
echo
proc with a string and specify return format asraw
import requestsr = requests.get('http://localhost:5050/echo',params={'v': 'Hello World', 'fmt':'raw'})print(r.text) # prints 'Hello World' directly -
Test the 'subtract' proc with a POST style request
import requestsimport jsonr = requests.post('http://localhost:5050/minus',data=json.dumps({'a': 25, 'b': 5}))print(json.loads(r.text))
PHP
- Test the
echo
proc with a number<?php$args = http_build_query(array("v"=>5));$data = file_get_contents("http://localhost:5050/echo?".$args);$r = json_decode($data, true);print_r("Echo returned ".$r["results"][0]["data"][0].PHP_EOL);?>