JOTPOT

JOTPOT
PongSoftwareJOTPOT ServerWhats my IP?Clock

JOTPOT Server Docs

JOTPOT Server Main Page
Please note that this page is still a work in progress, and is no where near complete. It may not look the best yet but the content should be good :)

Getting started

Welcome the the documentation for JOTPOT Server, this first section is a guide on getting started with JOTPOT Server.
JOTPOT Server is a multipurpose server that is designed to elegantly fulfil a variety of tasks. The most simple function of JOTPOT Server is as a standard file server. Even if you are starting a more complex server, the following setup is almost universal.

Download


To start the first method, we will download the basic files that we need, all these downloads are available on jotpot.uk/server. JOTPOT Server is written in JavaScript for Node.js and also a bit of Go. The main server software is written for Node.js, with some more advanced features such as the load balancer written in Go. For this reason, there are a few different ways of running JOTPOT Server. The first is to run the server with Node.js. To do this, make sure that you either have Node.js installed or have a binary for it. It is recommended that you use a stable version from v6 onwards. And make sure that it is up-to-date with all the latest security and stability updates. Node.js can be downloaded from nodejs.org/en/download. Once installed, download and extract the Node.js source from jotpot.uk/server.
Here is an example of downloading the source from the Linux command line:
	wget https://www.jotpot.co.uk/releases/25E/jps.tar.gz
	tar -xzf jps.tar.gz
	rm jps.tar.gz
The source should then be in your current directory.
This source contains the basic configuration so there is no need to download anything else if you are using this method.
Another method of downloading JOTPOT Server is to download a version of Node.js that contains JOTPOT Server and has already been compiled into a binary, these are also available for a variety of platforms at jotpot.uk/server. If your platform is not supported you can compile your own (instructions on the download page), or just run it from Node.js (which is probably easier at this point).
When you have the correct binary, you will also need a configuration file and an error page, these can be downloaded also from jotpot.uk/server under the downloads titled 'A simple HTTP server connfig.json file' and 'The default error page'. Put these downloads into the same directory as the binary, and you are ready to go!

Setting things up

JOTPOT Server looks for the files to serve in the sites directory, each host should have a directory within this where it's webspace is contained. For example, if you were hosting the website 'example.com', then in your directory with the main server files - the one with the configuration file etc. - you would setup a directory named 'sites', and within that, one named 'example.com'. Please notes that port numbers other than 80 and 443 (for default HTTP and HTTPS) are included in the directory name, so when the server receives a request with the host 'example.com:8080', JOTPOT Server looks under 'sites/example.com;8080' - note how the colon is replaced with a semi-colon.
For localhost, we can set this up like this on Linux:
	mkdir sites
	mkdir sites/localhost
Or on Windows:
	md sites
	md sites/localhost
When JOTPOT Server receives a request, by default, it looks for that file, it will attempt to stat it. So a request for 'example.com/hello.html' would cause the server to stat 'sites/example.com/hello.html', if the file exists and is a file, then JOTPOT Server will serve that file. If it is a directory, then it will then attempt to stat 'sites/example.com/hello.html/index.html', and if that is a file, it will serve that. If 'sites/example.com/hello.html' doesn't exist, it looks for the filename, however with a '.page' extension, so 'sites/example.com/hello.html.page'. This can be useful if you would like 'example.com/hello' to load 'sites/example.com/hello.page'. If no file can be found, it responds with a 404, we will talk more about error responses later.
However, if the directory 'sites/example.com' doesn't exist, it will return a 404, unless the 'useDefaultHostIfHostDoesNotExist' property in the config.json file is set to true (from 25F onwards), in which case, it will act as if the host is the 'defaultHost' property in the config.json file, so if the default host were 'default' and the 'sites/example.com' directory didn't exist, it would instead look in the 'sites/default' directory.

Before you run, you might want to change a few settings in the config.json file. THe first one you might want to change is the port for the default HTTP server. It will be set to port 80, the default port for HTTP, however on Linux, you have to run it as root to be able to use that port (as is is below port 1024, and thus a privileged port) and also some other programmes you have running might be using that port, such as skype using port 80 on windows. If the port you are trying to use is in use, you will get the error: EADDRINUSE (error address in use), that is a sign you need to stop the programme using that port or change the port.
You can change the port by looking under the httpservers property in the config.json file and changing ' "port": 80, ' to ' "port": 8080, ' or whatever number you like.
You will then need to rename your localhost directory from 'localhost' to 'localhost;8080' (replace 8080 with the port number you used).

Making a simple website

So obviously, as a web server, it serves HTML to the browser. This tutorial is made with the assumption that you understand basic HTML, if you don't check out W3Schools HTML tutorial or MDN HTML Basics (or both if you have too much time).
Before we run, we will create a basic website for you to test it out on.
For the sake of this tutorial, we recommend creating 3 files, index.html, page2.html and page3.page - you can write whatever HTML you want inside these files, and save them into 'sites/localhost;<YOUR PORT NUMBER HERE>'
		Your directory structure might now look a bit like this:
		
		J:.
		│   config.json
		│   errorTemp.jpt
		│   jps.exe
		│
		└───sites
		    └───localhost;8080
		            index.html
		            page2.html
					page3.page
	
	

Run!

Running JOTPOT Server is simple, if you downloaded the binary, just navigate to the directory with your config.json file, errorTemp.jpt and sites directory and run the jps or jps.exe. For example on Linux:
	/ $  cd /path/to/jotpot/server
	/path/to/jotpot/server $  ./jps
Or on windows:
	/> cd /path/to/jotpot/server
	/path/to/jotpot/server> jps
If you downloaded the Node.js source and have Node.js installed, here is an example of how to run it on Linux:
	/ $  cd /path/to/jotpot/server
	/path/to/jotpot/server $  node run
Or on windows:
	/> cd /path/to/jotpot/server
	/path/to/jotpot/server> node run
On windows, you will have to add a firewall exception, and on Linux, if you are creating a server on a privileged port (port number below 1024), you will have to run it as root, so begin the command with sudo - although this isn't recommended, you can set it up so that traffic into port 80 goes to port 8080 for example either on your router or with iptables on Linux, there is a guide from nixCraft here.
Now, you can load up your browser, and head to http://localhost:<YOUR PORT NUMBER HERE>. This will load up the index.html page in your localhost;<YOUR PORT NUMBER HERE> directory. Then, go to http://localhost:<YOUR PORT NUMBER HERE>/page2.html and you will see your other web page, or go to http://localhost:<YOUR PORT NUMBER HERE>/page3 to see your page3.page file.

Going a bit further (just a bit, we haven't even got to extensions yet ;)

Now, you can try and access your server from another computer! To do this, find your local IP address, in Linux, use the ifconfig command, work out which interface you are using (mine is eth0, as it is the first eth (ethernet connection), you might be using wlan0 or a separate one) and read off the inet addr value, for example 192.168.1.103. And on windows use the ipconfig command, work out which adapter you are using, mine is the 'Ethernet adapter Ethernet', as mine is an ethernet connection, and read off the IPv4 Address value, again could be something along the lines of 192.168.1.103.
Remember those numbers. Go to another PC (for now, make sure it is on the same local area network (LAN) as the PC you are using as the server), and open the web browser. No go to http://<YOUR.IP.ADDRESS.HERE>:<YOUR PORT NUMBER HERE> (you don't need to add the :PORT part if you are using port 80 as 80 is the default port for HTTP).
You will notice that it responds with a 404: Not Found error, this is because it is now looking in 'sites/<YOUR.IP.ADDRESS.HERE>:<YOUR PORT NUMBER HERE>' for index.html, we could solve this be creating a new directory with that name. But we could also use a feature of JOTPOT Server called host aliasing. This allows you to set an alias up for a host, so host-a.com could be processed as host-b.com. We can set this alias in the config.json file. Find the property named "hostAlias". In the default config, the value will be '{}', if we set it to '{"host-a.com":"host-b.com"}', then host-a.com will be handled as host-b.com. This can continue as such: '{"host-a.com":"host-b.com", "some-other-website.co.uk":"some-other-website.com"}'. With a comma separating the values.
So to set up the alias you want, we can set the "hostAlias" property to '{"<YOUR.IP.ADDRESS.HERE>:<YOUR PORT NUMBER HERE>":"localhost:<YOUR PORT NUMBER HERE>"}'
Then, reboot the server. So this by focusing on the command window it is running in and pressing ctrl+c to kill the programme. If this doesn't work on Windows (due to changed defaults), just close the window. Then rerun the server and the config.json will be reloaded. Now try from the other computer again and your index.html file should pop up!

To connect to your server from another PC that is not on your network, you will need to know your global IP address, the one that points to you from outside of your LAN. You can get your global IP address from jotpot.uk/whatsmyip. You will then need to set up your router to let traffic on your chosen port get to your PC, this is known as port forwarding. Make sure that the port you want to use externally (this could be port 80, the default for HTTP remember or another port), forwards to the port that the server is running on on your PC.
There are some guides available for setting port forwarding up from: PCWorld, wikiHow, BT, How-To Geek and many others with a quick Google search for "how to set up port forwarding" (the How-To Geek one goes in to the most exciting detail)
Then, you will need to set up another host alias (just as we did before), but this time from <YOUR.GLOBAL.IP.ADDRESS>:<The port you chose to forward from> - remembering that if we chose port 80, we don't need the ':80' at the end. And still to 'localhost:<The port your server is running on>'
Reboot the server once more and try to connect via your global IP. If all is good, you should be able to access your web server from anywhere in the world now. However you might need to bare in mind that if you have a dynamically assigned IP address, your IP address will change from time to time, so you might need to keep on top of that.
From there, you can buy a domain name and point that to your IP and turn your website into whatever you like.
Buying a domain is one way to prevent the constant changing of the host aliases in the config file, but, as mentioned earlier, another way would be to use the default host.
So for this, lets rename out localhost directory to 'default', this could be anything, but default makes sense. We should then set our "defaultHost" property in the config.json file to the name of our directory. Luckily, the default one you downloaded, already has this. Then make sure that the "useDefaultHostIfHostDoesNotExist" property is set to true, before rebooting the server. You can also remove all the aliases now as they are no longer required.
After the reboot, no matter what host you use to connect to your server, as long as there isn't a directory for it, it will use the 'sites/default' directory, however if you were to register 2 domains, say "host-a.com" and "host-b.com", you could still have separate directory's for them 'sites/host-a.com' and 'sites/host-b.com', while everything else will go to 'sites/default'.

The rest of the docs dive deeper into JOTPOT Server, it covers the config.json file and also extensions - that give you the power to modify the behaviour of JOTPOT Server and add server-side logic and scripting. Have fun and thank you for using JOTPOT Server :)
JOTPOT Server is all open source on GitHub, so if you encounter any problems, or have any features would like to suggest or add yourself, head over there.

The config.json file

This JSON file contains the basic configuration for JOTPOT Server. There are simple versions and demo versions available from jotpot.co.uk/server
Properties:

'httpServers': Array. Each item of the array should be an object containing the HTTP server options.
'httpsServers': Array. Each item of the array should be an object containing the HTTPS server options.
'redirectToHttps': Array. Each item of the array should be a string of any domains you want to be permanently redirected to the https version of the site.
'canBeHttp': Array. Each item should be paths you do NOT want redirecting to HTTPS if the domain normally gets redirected.
'dataPort': Number, the port you would like the data connections to come though, see data connections.
'hostRedirects': Object. Format: {"host_you_want_redirecting.com":"host_to_redirect_to.com"}
'hostAlias': Object. Similar to hostRedirects however rather then redirecting the server will handle the request as if it came from the domain you set - without the user being redirected.
'pageAlias': Object. The same as hostAlias however with pages instead. Note the format: {"example.com/page1":"example.com/page2"}. If the user goes to example.com/page2, it will be handles as if it were example.com/page1.
'addVarsByDefault': Boolean, true to replace anything served in the format "$:::<var name>:::$" with the value of the variable or false to not replace be default.
'doVarsForIfNotByDefault': Array of Strings. The strings should be in the format: "<hostname>/<path>", any pages included in this array will have variables added to them even if doing them by default is set to false.
'cache': Array of Strings. Each item is in the format "<host>/<page>", this will be cached.
'errorTemplate': String. The file to use as the error page.
'defaultHost': String. The host to use by default if the http request contains no host header or useDefaultHostIfHostDoesNotExist is true and the host requested doesn't exist.
'useDefaultHostIfHostDoesNotExist': Boolean. true if the default host should be used like an alias if the host the user is requesting does not exist.
'behindLoadBalencer': Boolean. true if headers set be the JOTPOT Server load balencer should be used, for example when determining the source IP address or if the request was HTTPS.

HTTP Server Options:
'port': Number, the port you would like the server to be opened on.

HTTPS Server Options:
'port': Number, the port you would like the server to be opened on.


What are JOTPOT Server extensions and how do they work?

JOTPOT Server allows JavaScript files to be run and take control over the server, anything is possible via extensions and 'limited' extensions can be run to ensure an extension can only handle requests etc. from a specific domain/domains for security and stability.
Any file in the working directory of the server, with the full filename ending in '.jpe.js' will be loaded as extensions. There are 2 types of extensions, 'Master' extensions, and 'worker' extensions. JOTPOT Server runs using the Node.js cluster modules, this means that there is a master process and then an amount of workers. The master process runs all extensions (where the server.isMaster variable will be true) and each worker runs all the extensions (where the server.isMaster variable is false). They have some shared API features however some different features.
Every extension is loaded with the standard Node.js require function, console object, setTimeout along with the setInterval and setImmediate functions.
There is also a 'server' object for controlling and interacting with the current JOTPOT Server instance, documented below.
The most key consent of extensions is server.handle, and for developing simple applications, it can be all that is needed.


'server' object

The server object is an object available is master and worker extensions, however with differences in each.

server.callFunc(funcName[, ...arguments])

Availability:
  • Master extention: No
  • Worker extention: Yes
  • Limited master extention: No
  • Limited worker extention: Yes
Added: 25A
  • funcName <String> Name of the function to call.
  • ...arguments Arguments to call the function with.
Calls a function in the master process that was set by server.setFunc() in a master extension.
Returns a promise that resolves with the returned value of the called function.

server.config

Availability:
  • Master extention: Yes
  • Worker extention: Yes
  • Limited master extention: No
  • Limited worker extention: No
Added: 25A
    Object created from the config.json file, used to determine settings during runtime, you can modify it and the changes will be applied.
    Please note that some changes such as server.config.dataPort are set when JOTPOT Server loads and thus changing them after the initial load will not have any effect. These can however be changed as soon as the extension is loaded as the server is set up after the extensions are loaded.

    server.createAccountSystem(options)

    Availability:
    • Master extention: No
    • Worker extention: Yes
    • Limited master extention: No
    • Limited worker extention: Yes
    Added: Pre 25A
    • options <Object> Options to create the account system with.
    Created an account system with the given options, documentation coming soon.

    server.getData(request)

    Availability:
    • Master extention: No
    • Worker extention: Yes
    • Limited master extention: No
    • Limited worker extention: Yes
    Added: Pre 25A
    • request <Server Request> Request to read the data from.
    Returns a promise that resolves with all data sent by the client. It resolves when the request is ended.

    server.getGlobal(variableName[, modifying])

    Availability:
    • Master extention: Yes
    • Worker extention: Yes
    • Limited master extention: Yes
    • Limited worker extention: Yes
    Added: Pre 25A
    • variableName <String> Name of the variable to retrieve.
    • modifying <Boolean> Whether or not the variable is being 'modified'.
    Gets a server wide global variable. In the master process, it will resolve instantly.
    Returns a Promise, resolves with the value of the global variable.
    See also: server.setGlobal()

    server.getMimeType(filename)

    Availability:
    • Master extention: Yes
    • Worker extention: Yes
    • Limited master extention: No
    • Limited worker extention: No
    Added: Pre 25A
    • filename <String> The filename to get the mime type of.
    Returns the mime type of the filename passed.

    server.getUserID(request, response)

    Availability:
    • Master extention: Yes
    • Worker extention: Yes
    • Limited master extention: No
    • Limited worker extention: No
    Added: Pre 25A
    • request <Server Request> The request object to get the user ID from.
    • response <Server Response> The response object to get the user ID from.
    Returns the user ID of the user making this request. If the user doesn't already have a user ID it will create one for it.
    Note that if it creates a new user ID, the set-cookie header will be set, and overwriting it will cause the user ID to be invalidated.

    server.handle(events, callback)

    Availability:
    • Master extention: Yes
    • Worker extention: Yes
    • Limited master extention: Yes
    • Limited worker extention: Yes
    Added: Pre 25A
    • events <Array<String>|String> An event or array of events this function should handle.
    • callback <Function> Function to call to handle the event.
    Setting a handle for an event allows the function to overwrite or add to the default behavior for the event being handled.
    The function should return undefined, a Boolean or a promise - that should resolve with undefined or a Boolean.
    If the function returns true or the returned promise resolves true then the server will consider the event 'handled' and thus not continue with the default behavior
    All the events that can be handles are detailed in the Server Events section.

    server.limited

    Availability:
    • Master extention: Yes
    • Worker extention: Yes
    • Limited master extention: Yes
    • Limited worker extention: Yes
    Added: Pre 25A
      true if the extension is limited, false if not.

      server.loadExt(path[, lock])

      Availability:
      • Master extention: Yes
      • Worker extention: Yes
      • Limited master extention: No
      • Limited worker extention: No
      Added: Pre 25A
      Notes: Available in limited extensions until 25D
      • path <String> Path of the file to run.
      • lock <Lock> Optional lock to apply to the extension.
      Loads and runs the path given as an extension. If a lock argument is given, that lock will be applied to the extension. Use the server.lock class to create a valid lock.
      If the current extension is a master extension, the new extension will be loaded as a master extension and if the extension is a worker extension the new extension will also be loaded as a worker extension, only in the process of the current extension - so to ensure an extension can handle all server events it must be loaded all times its parent extension is loaded.

      new server.lock([variableSandbox, mode, hosts])

      Availability:
      • Master extention: Yes
      • Worker extention: Yes
      • Limited master extention: No
      • Limited worker extention: No
      Added: 25A
      Note: From 25D the server.lock is actually an extension of the actually lock class to prevent it from being overwritten and causing errors.
      • variableSandbox <String|null> Name of sandbox to use for global variables, or null if no sandbox.
      • mode <Number> Optional lock to apply to the extension.
      • hosts <Array<String>> Array of strings this extension is allowed to handle events for.
      If variableSandbox is a string, all server wide global variables set with setGlobal and retrieved with getGlobal (or modGlobal) will be stored within an object named 'variableSandbox' within the standard global object - meaning that the extension cannot access global variables from other extensions with no or different sandboxes, however extensions with no sandbox can access the variables be getting the global variable named 'variableSandbox' - which will be an object of the variables.
      If host limits are used (so mode >= 1), the extension will only be allowed to handle events for that domain, so if 'hosts' is ["www.example.com"], then any handles created by it for "request" or similar events will only handle these events for requests to "www.example.com", so it will not be allowed to handle events for "www.jotpot.co.uk".
      Mode can only be 0, 1 or 2 (defaults to 2). If mode is 0, only the variable sandbox will be applied, if mode is 1, variable sandbox will be applied and the host limits will be applied, mode 2 behaves identically to mode 1 right now however new behavior will be added in the future for mode 2.
      The object created should be used when calling server.loadExt()

      server.modGlobal(variableName)

      Availability:
      • Master extention: No
      • Worker extention: Yes
      • Limited master extention: No
      • Limited worker extention: Yes
      Added: 25B
      • variableName <String> Name of the variable to modify.

      server.multiPartFormDataParser(request, callback)

      Availability:
      • Master extention: No
      • Worker extention: Yes
      • Limited master extention: No
      • Limited worker extention: Yes
      Added: 25E
      Note: Not currently recomended due to lack of testing.
      • request <Server Request> Request to parse the data from.
      • callback <Function> Function to be called with all new data.
      Returns a Promise, that resolves when all data has been recieved and parsed.
      The callback is called whenever a new field is recieved. It is sent with a Data class as the only argument.
      The Data class is an extension of the standard Node.js readable stream and the data recieved for the current field will be piped out of it. It also has 3 extra popities: name, headers and setup. The name property contains the name of the field, headers contains an object of the parsed headers of the field, and setup is used for internal use.

      server.pages

      Availability:
      • Master extention: No
      • Worker extention: Yes
      • Limited master extention: No
      • Limited worker extention: No
      Added: Pre 25A
        Variables used for caching, documentation coming soon.

        server.reloadConfig()

        Availability:
        • Master extention: Yes
        • Worker extention: Yes
        • Limited master extention: No
        • Limited worker extention: No
        Added: 25A
        Note: Not available in the master process until 25D
          Reloads the config.json file.

          server.sendCache(file, response, request)

          Availability:
          • Master extention: No
          • Worker extention: Yes
          • Limited master extention: No
          • Limited worker extention: No
          Added: 25E
          • file <String> URL to send coresponding file for.
          • response <Server Response> The response to send the error to.
          • request <Server Request> Optional, the request to get the ID from for improved logging.
          Exposes an internal function that has been around scince the first release.
          server.sendCache sends a cache to the response. The cache argument is writen to the response into Node.js's response.write, so any type that can be writen to that will be acceptable as the cache argument.
          The code argument specifies the response code to be sent.
          Returns a promise that rejects on an unexpected error, and resolves with an array. Index 0 of this array is a boolean, true if the response was sent succesfully and false if not. If index 0 is false, index 1 is the error.
          Chunked encoding is used unless there are no pipes, in which case the content-length header will be set the the length property of the cache argument.

          server.sendError(code, message, response)

          Availability:
          • Master extention: No
          • Worker extention: Yes
          • Limited master extention: No
          • Limited worker extention: No
          Added: Pre 25A
          • code <Number> HTTP response code to send.
          • message <String> The message to display on the error page.
          • response <Server Response> The response to send the error to.
          Sends a full response based on the error code with the 'errorTemp.jpt' file (from the working directory of the server) with all the error details.

          server.sendFile(file, response, request)

          Availability:
          • Master extention: No
          • Worker extention: Yes
          • Limited master extention: No
          • Limited worker extention: No
          Added: 25E
          • file <String> URL to send coresponding file for.
          • response <Server Response> The response to send the error to.
          • request <Server Request> Optional, the request to get the ID from for improved logging.
          Exposes an internal function that has been around scince the first release.
          server.sendFile sends the correct file as the response to the request. For example if file is 'example.com/hello.html', it will serve './sites/example.com/hello.html'.
          Returns a promise that rejects on an unexpected error, and resolves with an array. Index 0 of this array is a boolean, true if the response was sent succesfully and false if not. If index 0 is false, index 1 is the error.
          It pipes through all the correct pipes, including the vars pipe if it should be added for the file given. Chunked encoding is used unless there are no pipes, in which case the content-length header is set to the size of the file being served.

          server.setFunc(functionName, function)

          Availability:
          • Master extention: Yes
          • Worker extention: No
          • Limited master extention: Yes
          • Limited worker extention: No
          Added: 25A
          • functionName <String> Name of the function to set.
          • function <Function> The function to assign to the function name.
          Sets a function that can be called by any of the workers via server.callFunc(). Each seperate lock gets its own scope for functions - based on the variable scope.

          server.setGlobal(variableName, value)

          Availability:
          • Master extention: Yes
          • Worker extention: Yes
          • Limited master extention: Yes
          • Limited worker extention: Yes
          Added: Pre 25A
          • variableName <String> Name of the variable to retrieve.
          • value Value to set the variable to.
          Sets a server wide global variable. In the master process, it will resolve instantly.
          Returns a Promise, resolves when the value of the variable has been set.
          See also: server.getGlobal()

          server.vars

          Availability:
          • Master extention: No
          • Worker extention: Yes
          • Limited master extention: No
          • Limited worker extention: No
          Added: Pre 25A
            Object containing global variables to be inserted into pages.
            If server.vars = {'test1':'hi','test2':'world'}, then in a page served containing the contents '$:::test1:::$ - $:::test2:::$' will be served as 'hi - world'.
            Note that ServerResponse.vars will also be added this way, with a higher priority (with a lower priority until 25D).


            Server Events

            JOTPOT Server has a serese of events that extensions can handle to add behavior to or to overwrite the behavior of.
            Please see server.handle() for handling events.

            Events:

            • 'ready' event: This is the first event to fire, this event is fired when the current process is up and ready. This is fired for both master extensions and worker extensions and is the only event currently for master extensions. It cannot be overwritten, so the return value is ignored. The handler is called with no arguments.
            • 'request' event: This event is fired whenever a request is received, this event is fired before any redirects happen, such as redirects to HTTPS or redirects to the login page, so this should generally not be handled. The default behavior can be overwritten to if the handler returns true or returns a promise that resolves true, JOTPOT Server will stop handling the request. The handler is called with 2 arguments, the request object and the response object.
            • '<domain>/request' event: This is the equivalent to the 'request' event however only fires for the domain before the '/'
            • 'fullrequest' event: This event is fired after a request is redirected and has page/host aliases applied, this event is however fired before any authentication checks happen, so this should generally not be handled if an account system is active of the page. The default behavior can be overwritten to if the handler returns true or returns a promise that resolves true, JOTPOT Server will stop handling the request. The handler is called with 2 arguments, the request object and the response object.
            • '<domain>/fullrequest' event: This is the equivalent to the 'fullrequest' event however only fires for the domain before the '/'
            • 'allowedrequest' event: This event is fired when the server is ready to respond to the event, the user will have gone through all redirects, any aliases will have been applied and the user will be authenticated to access the page they are requesting. In most cases, this is the best event to handle for server side rendering, analytics and most other use cases.
            • '<domain>/allowedrequest' event: This is the equivalent to the 'allowedrequest' event however only fires for the domain before the '/'


            Using server.handle

            So, lets say you want to render a page serverside for the user, you could use the serveer.handle function to create this functionality.
            When you handle any request event, so 'request', 'fullrequest', 'allowedrequest' or any host specific request, the handler function will receive 2 arguments, the request and the response object. These are documented below.
            Here is an example:
            	//Handle the request when we know it is allowed, to ensure that
            	// we don't serve a page to a user that isn't logged in.
            	server.handle('allowedrequest', (req, resp) => {
            		
            		//The request and response object have everything the standard
            		// Node.js objects have however with some modified properties
            		// and some additional ones.
            		
            		//Note how the domain is at the start of the req.url, see
            		// req.url in the request docs below for how it is different.
            		// You might also want to use req.purl here instead.
            		if (req.url === 'www.exmaple.com/content.html') {
            			
            			//Call you own function to hamdle the request and the
            			// response as you would in any other Node.js server.
            			renderContentPage(req, resp) ;
            			
            			//Return true to say that this has handled the event
            			// so the default behavior gets overwritten.
            			return true ;
            			
            		}
            		
            		//If we haven't handled it, return false so the server 
            		// continues with the default behavior for the request.
            		return false ;
            		
            	});
            	

            The 'request' ('IncomingMessage') object.

            The 'request' object is passed as the first argument to any hander function handling a request - with the second argument always been the response object. It is the Node.js IncomingMessage object however has some modified properties and some added properties to make working with it easier. All of these changed/additional properties are listed below.

            request.accualHost

            Added: Pre 25A
              Similar to request.orig_url, it is the host the request was originally made with, thus this is without the host alias applied.
              This is not available for the request handle.

              request.fullurl

              Added: 25A
                This is what will appear in the users URL bar, for example 'https://www.example.com:443/path/to/page.html'. Note that these elements will always be included.

                request.host

                Added: Pre 25A
                  request.host will be equal to the domain the request is been made to, after aliases have been handled, so for the fullrequest and allowedrequest events, it will be the alias.
                  This is not available for the request handle.

                  request.ip

                  Added: 25E
                    request.ip if the IP address of the user making the request. If there is an x-forwarded-for header, the IP address is set the that over the accual IP address.
                    If config.behindLoadBalancer is true, the jp-source-ip header set by the load balancer will be used as the source IP.
                    Also see request.sourceIp.

                    request.orig_url

                    Added: Pre 25A
                      This will be the original URL requested by the client. See request.url for details on how it is changed.
                      This is not available for the request handle.

                      request.overHttps

                      Added: Pre 25A
                        Alias for request.secure (was added before request.secure and left in for backwards compatibility purposes), so true if the request was made over HTTPS and false if not.

                        request.path

                        Added: Pre 25A
                          The requested path (thus without the host) with all occurrences of '..' removed.
                          This is not available for the request handle.

                          request.pathname

                          Added: 25E
                            request.path however without the query.
                            This is not available for the request handle.

                            request.purl

                            Added: 25A
                              Equivalent to if request.fullurl was passed to Node.js's url.parse.

                              request.secure

                              Added: 25D
                                Whether or not the request and response is secure, so true if the request was made over HTTPS and false if not.
                                From 25E onwards, if config.behindLoadBalancer is true, the jp-source-secure header set by the load balancer will be set, even if the load balancer made the request via HTTP to the server, the value will be determined by the clients connection to the load balancer.

                                request.secureToServer

                                Added: 25D
                                  Whether or not the connection to the load balancer is HTTPS. If there is no load balancer, it is equal to request.secure

                                  request.remoteAddress

                                  Added: 25E
                                    request.remoteAddress if the IP address of the client making the request. Unlike request.ip, it ignores the x-forwarded-for header.
                                    If config.behindLoadBalancer is true, the jp-source-ip header set by the load balancer will be used as the source IP.

                                    request.url

                                    Added: Pre 25A
                                    Note: Before 1.2.0, request.url was all lower case.
                                      The URL that the client requested, however with all occurrences of '..' removed to prevent the request from going into a parent directory. It also has the host concatenated before the path, so a request for '/hello.html' with the host 'www.example.com', req.url would be 'www.example.com/hello.html'.
                                      This is not modified for the request handle.

                                      request.user

                                      Added: Pre 25A
                                        This is the user ID of the user of the current user, please note that this is only set when it is required for the user to be authenticated for the page. And thus also only available in the allowedrequest handle.


                                        The 'response' ('ServerResponse') object.

                                        The 'response' object is always passed to the request hander as the second argument, and similar to the 'request' object is the Node.js ServerResponse object however with a couple of added properties for ease of use. These added properties are documented below.

                                        response.pipeThrough

                                        Added: Pre 25A
                                          This is an array that by default is empty. When the response is sent, it will be piped through all the pipes in this array before been piped to the client, meaning that you can add compression transform pipes, some templating solutions or more to this array and your response will be sent through them.

                                          response.vars

                                          Added: Pre 25A
                                            These are variables processed in the same way as server.vars however these are only for the current response and will overwrite any global variables.