ok-server
ok-server is simple web server implemented with node.js HttpSever. It can be extended by adding it new request handlers for the desired endpoints. It includes two default request handlers, one for the file requests and one for the API requests. It's API request handler is easily extendable. File handler supports partial file requests in addition to normal file transfer.
Table of contents
- Installation
- Usage
- Request-Handlers
- API System
- Reference
Installation
npm install ok-server
Usage
OKServer object can be initialized with createServer function of ok-server module or instantiating it with new keyword using ok-server property OKServer. Both methods enable extending of the OKServer class. Extending is preferable because it enables the use of event methods of the class.
Initializing with createSever
const okserver = require( "ok-server" );
const server = okserver.createServer({
logFolder: __dirname + "/log",
pulseFolder: __dirname,
optionsFile: __dirname + "/my-server.json"
});
Extendeding server class
const okserver = require( "ok-server" );
class MyServer extends okserver.OKServer {
constructor(options) {
super(options);
this.addMimeType({
".mp3": "audio/mpeg",
".wav": "audio/x-wav"
});
}
}
Initializing with extended server class
const okserver = require( "ok-server" );
const server = okserver.createServer({
serverClass: MyServer,
logFolder: __dirname + "/log",
pulseFolder: __dirname,
optionsFile: __dirname + "/my-server.json"
});
class MyServer extends okserver.OKServer {
constructor(options) {
super(options);
this.addMimeType({
".mp3": "audio/mpeg",
".wav": "audio/x-wav"
});
}
}
-- or --
class MyServer extends require( "ok-server" ).OKServer {
constructor(options) {
super(options);
this.addMimeType({
".mp3": "audio/mpeg",
".wav": "audio/x-wav"
});
}
}
const server = new MyServer({
logFolder: __dirname + "/log",
pulseFolder: __dirname,
optionsFile: __dirname + "/my-server.json"
});
Creating initial options file
Initial options file can be created by executing following source with command line flag /initServerOptions. It will create an option file including default option values. Default option values can also changed as can be seen in the example.
const okserver = require( "ok-server" );
const options = okserver.defaultOptions;
options.port = 3099;
options.defaultDirectory = "/sites/my-test/site";
options.mimeTypes[".mp3"] = "audio/mpeg";
options.mimeTypes[".wav"] = "audio/x-wav";
okserver.createServer({
optionsFile: "/sites/my-test/my-server.json"
});
Request Handlers
ok-server has two request handlers pre-implemented. Requests on api entry point are handled by the api request handler. File requests on both default directory and all virtual directories are handled by default the default hanlder.
Implementing and utilizing a new request handler
Request handlers can be implemented by creating a new request handler javascript module and loading it with server's loadHandler method. The module source must follow a structure similar to the one below. The following three conditions must be met:
- New request handler class must extend RequestHandler class defined in requesthandler.js,
- The class instances must be given a proper name representing the handler name.
- Module must export the new RequestHandler class defined in it.
The request handler is utilized by defining it as a virtual directory request handler. This is done using the server's addVirtualDirectory method by adding the handler name to the handlerName parameter.
Request handler prototype
const RequestHandler = require( "ok-server" ).RequestHandler;
class TestRequestHandler extends RequestHandler {
constructor (params = {}) {
params.name = "test"; // handler name
super(params);
}
onRequest( context ) {
const responseHeaders = {};
let responseBody = "";
let statusCode = 200;
// The code that inspects the request, adds response headers needed, and
// constructs a proper response body as string/stream.Readable
this.sendResponse( context, {
status: statusCode,
headers: responseHeaders,
body: responseBody
});
}
}
module.exports = TestRequestHandler;
Replacing the default request handler
After the server is initialized, the default request handler can be replaced with the server method loadHandler. The request handler object in the module has to be named as "default". See Request handler prototype above.
API System
ok-server has simple and easy facilities to create API services. These facilities includes means to define API requests, more specifically their names and parameters. API system will validate parameters of the requests and reponds with error message in case of invalid or missing parameters,
API request is sent on client (browser) side as http requests with POST method. The API request name and the request parameters are added to the body of the http request as the json object.
It also have two predefined API services.
API-request
The request object added to the body of the API request must be as follows.
{
name: string,
parameters: {
<parameter-name(1)>: boolean|number|object|string,
...,
<parameter-name(n)>: boolean|number|object|string
}
}
API request are done with the following function.
function apiRequest( onError, onSuccess, name, parameters = {}) {
const apiRoot = location.protocol + "//" + location.host + "/api";
const request = { name: name, parameters: parameters };
const xhr = new XMLHttpRequest();
xhr.addEventListener( "error", () => { onError( new Error( "E_LOAD" ));});
xhr.addEventListener( "abort", () => { onError( new Error( "E_ABORT" ));});
xhr.addEventListener( "load", function () {
try {
const response = JSON.parse(this.responseText);
if (response.succeed) {
onSuccess(response.content);
}
else {
onError(response.error);
}
}
catch (error) {
onError( new Error("E_PARSE: " + error.message ));
}
});
xhr.open( "POST", apiRoot );
xhr.setRequestHeader( "X-Requested-With", "XMLHttpRequest" );
xhr.setRequestHeader( "Content-Type", "application/json; charset=utf-8" );
xhr.send( JSON.stringify(request));
}
API-response
The response payload to the API request contains a stringified json object. In case of success the json object is as follows.
{
succeed: true,
requestName: string,
content: array|boolean|number|object|string,
elapsed: number
}
The response content property may contain the value of of any json-compatible data type. Elapsed
property indicates the elapsed time of processing the request in milliseconds..
In case of error the response payload contains following json object.
{
succeed: false,
requestName: string,
error: {
code: string,
message: string
},
elapsed: number
}
Pre-defined API requests
api
The content property of the response to the API request api contains complete specifications of the all currently implemneted API services as they are defined with okserver.defineApiRequest().
{
<request-name(1)>:
parameters: {
<parameter-name(1)>: {
type: string,
mandatory: boolean,
description: object,
default: boolean|number|object|string
},
...,
<parameter-name(n)>: {
type: string,
mandatory: boolean,
description: object,
default: boolean|number|object|string
}
},
description: object,
cargo: object
},
...,
<request-name(n)>: {
...
}
}
This API service is especially useful for creating automatic client-side API module. See an example of the source file here.
getConfig
By default, the content property of the response to the api request getConfig contains an empty object. In order to include the desired values to the object the onApiGetConfig method of the OKServer can be overwritten and the content filled with the name-values pairs as wanted.
Extending API
Implementing API extension module
The first thing is to create a new API extnesion module. Below is an example of the possible content of the module.
const okserver = require("ok-server");
okserver.defineApiRequest([
{
name: "myService1",
parameters: {},
worker: __myService1
},
{
name: "myService2",
parameters: {
firstname: {
type: "string",
mandatory: true,
description: { text: "First name" }
},
lastname: {
type: "string",
mandatory: true,
description: { text: "Last name" }
},
title: {
type: "string",
mandatory: false,
default: "Mrs."
description: { text: "Title" }
}
},
worker: ( context ) => {
// For array functions context is passed as function parameter
const p = context.request.parameters;
context.onSuccess( "Hello "
+ p.title + " "
+ p.firstname + " "
+ p.lastname + "!"
);
}
}
]);
function __myService1() {
// In regular functions context is available as this keyword
const ip = this.server.getRemoteIp( this.httpRequest );
this.onSuccess(ip);
}
Loading API extension module
API extension modules are loaded with OKServer extendApi method.
Defining new API requests
New API request is defined the API extension module with the OKServer method defineApiRequest.
API worker functions
The API request causes the worker function associated with it to be called. To this function is passed a Context object. If the function is an array function, Context object is passed as function parameter. In case of regular functions the context is available also as a value of this keyword.
Reference
Module ok-server
Functions
-
okserver.createServer( options ) - Creates an OKServer object with the desired options.
-
options See server options.
-
-
okserver.defineApiRequest(definition) - Creates the definition of a new API service.
-
definition object
{
name: string,
parameters: {
<parameter-name(1)>: {
type: string ("string"|"number"|"boolean"|"object")[,
mandatory: boolean ][,
default: string|number|boolean|object ][,
description: object]
},
...,
<parameter-name(n)>: {
type: string ("string"|"number"|"boolean"|"object")[,
mandatory: boolean ][,
default: string|number|boolean|object ][,
description: object ]
}
},
worker: function [,
description: object ]
} -
Return value: none
-
Properties
- defaultOptions object - default options object whose values are used on creating and starting the server in the case these values are not overwritten in the options file or passed as the options parameter when creating the server. These option values are also written to the options file when it is created.
- OKServer class - OKServer class for instantiating server object or extending one.
- RequestHandler class - RequestHandler class for extending RequestHandler in order to create a new request handler.
OKServer class
Initialization
new require("ok-server").OKServer(options);
Options
-
accessFiltering array - Contains access filtering objects with following properties.
- filter:
- path string
- status string ("forbidden"|"permitted")
- filter:
-
apiEntryPoint string - Name of the virtual directory that serves as the entry point for the API requests. Default value is "api".
-
apiExtensions array - Full names of the API extension mofule files to be loaded before the server starts. Default is [].
-
cors object - Contains CORS related properties needed when client sends a pre-flight OPTIONS request.
- allowCredentials boolean - If the allowCredentials is set as trua the Access-Control-Allow-Credentials response header is included into the response with value true. Default value is false.
- allowHeaders string - Contains headers to be written in Access-Control-Allow-Headers response header. Default value is "authorization, content-type, x-requested-with".
- allowOrigin string - Contains a comma-separated list of origins (or * character) against which the origin header of the request is checked. If the origin header of the request matches, it is written in the Access-Control-Allow-Origin header of the response. If the origins list contains the * character only, it is written in the Access-Control-Allow-Origin header. Default value is "*".
- maxAge number - Contains a numeric value written in Access-Control-Max-Age response header. Default value is 7200.
-
defaultDirectory string - The full path of the root virtual directory. Default value is __dirname + "/examples/site".
-
defaultDirectoryName string - The name of the default directory that is set as the name for the root virtual directory. The default is "/".
-
defaultDocument string - Name of the default HTML document. Default value is "index.htm".
-
httpsOptions object - Contains options needed in creating HttpsServer. Can be either { pfx: string, passphrase: string } or { key: string, cert: string }. Default value is { pfx: "%OKSERVER_PFX%", passphrase: "%OKSERVER_PHRASE%" }. The value of the passphrase property may include - instead of a password - the name of the file that contains the actual password.
-
logApiRequests boolean - Indicates whether the API requests are written to the log file. Default value is false.
-
logFileRequests boolean - Indicates whether the file requests are written to the log file. Default value is false.
-
mimeTypes object - Includes MIME types supported by the server as the following object.
{
<extension(1)>: string,
...,
<extension(n)>: string
}OKServer supports following MIME types by default:
- css text/css; charset=utf-8
- htm text/html; charset=utf-8
- html text/html; charset=utf-8
- js application/javascript; charset=utf-8
- json application/json; charset=utf-8
- bmp image/bmp
- gif image/gif
- jpeg image/jpeg
- jpg image/jpeg
- png image/png
- pnz image/png
- tif image/tiff
- tiff image/tiff
- pfd application/pdf
- txt text/plain; charset=utf-8
-
optionsFile string - The full name of the JSON options file where the server's options are read from. Options in the file are overwritten by the options passed as options parameter to the createServer function or OKServer constructor. Default value is __dirname + "options.json".
Name of the JSON file where options are read from.
-
port number - Port number for the http.Server. If set as 0, the server is not instantiated. Default value is 3002.
-
pulseFolder string - Full name of the folder where the pulse file is written. The purpose of the Pulse is prevent the server starting if the script is re-run. If the options is not set, pulse does not start.
-
pulseInterval number - The interval as milliseconds where the pulse file is rewritten. Default value is 1000.
-
serverClass class - The class of the server object to create. It must be inherited from the OKServer. Default value is OKServer.
-
sslPort number - Port number for the https.Server. If set as 0, the server is not instantiated. Default value is 3002.
-
virtualDirectories object,
{
<name(1)>: { path: string, defaultDocument: string, handler: string },
...,
<name(n)>: { path: string, defaultDocument: string, handler: string }
}
Methods
-
addForbiddenPath( path ) - Adds a forbidden path to the server. This path is not accessible for the client.
- path string
- return value: OKServer
-
addMimeType( fileExtension, type ) - Adds a new type into the server's supported MIME types list.
- fileExtension string
- type string
- return value: OKServer
-
addPermittedPath( path ) - Adds a permitted path to the server. It is only meaninful if the parent of the added path is a forbidden path.
-
addVirtualDirectory( params ) - Adds a new virtual directory to the server and associates a request handler for it.
-
params object
- name string
- path string
- defaultDocument string - Default value is OkServer.defaultDocument.
- handlerName string - Default value is "default".
- parent VirtualDirectory - Default value is the base virtual directory creatad by the server according by the defaultDirectory and the defaultDirecotyName option values.
- return value: string - Return value is a string that indicates the success of the action. In case of success, the value is "OK". The value E_UNKNOWNHANDLER indicates that the handlerName parameter refers to a non-loaded handler. The value E_PATHNOTFOUND indicates - when the path parameter is included - the folder to which the path is assigned does not exist. The value E_ALREADYEXISTS indicates that the virtual directory already exists.
-
params object
- extendApi(apiExtensionModule) - Extends the API system with new api extension modules.
-
getRemoteIp( request ) - Solves the remote IP address of the http request.
- request http.IncomingMessage
- return value: string
-
getVirtualDirectory( name, parent ) - Returns a virtual directory by it's full name.
- fullname string - A string value representing the name of the directory as it is written in the URL address.
- parent VirtualDirectory - The parent directory of the virtual directory to be retrieved. Default is the root virtual directory.
- return value: VirtualDirectory
-
getVirtualDirectoryPath( name, parent ) - Returns the path of the virtual directory by the name of the directory.
- name string - A string value representing the name of the directory as it is written in the URL address.
- parent VirtualDirectory - The parent directory of the virtual directory to be retrieved. Default is the root virtual directory.
- return value: string
-
isForbidden(url) -> boolean - Indicates whether the url points to a forbidden path. This method is is depracated
- return value: boolean
-
isPermitted(url) -> boolean - Indicates whether the url points to a permitted path. This method is is depracated
-
loadHandler( module|modulename ) - Loads a new request handler module
- module string - The name of the module or module
- return value: OKServer
-
removeMimeType(ext) - Removes a MIME type from the list of the supported MIME types.
-
setResponseCookie( response, cookie, encoder ) - Adds a cookie to the Http response by adding a Set-Cookie header.
- response: http.ServerResponse
-
cookie object|array - Cookie object or array of cookie objects.
- name string, mandatory
- value string, default: "" (encoded with the encodeURIComponent function)
- path string, default: "/"
- domain string
- expires Date
- expirationDays number
- maxAge number
- httpOnly boolean
- sameSite boolean (true: "strict", false: no sameSite attribute) or string ("strict"/"lax")
- secure boolean
- encoder function, default: encodeURIComponent
-
start( params ) - Starts the server i.e. the http.Server or https.Server or both.
-
params object
- onError function(error) - Called in the case of error.
- onSuccess function() - Called when server is started listening.
-
params object
-
stop( onStop ) - Stops the server.
- onStop function() - Called when server is stopped listening.
-
onApiApi( onError, onSuccess, context, iface ) - An event method that is triggered just before the response to the request api is sent. Provides an opportunity to modify API specifications, for example, to complete api documentation. Overwrite this in child class.
-
onApiGetConfig( onError, onSuccess, context, config ) - An event method that is triggered just before the response to the request getConfig is sent. Provides the opportunity to complete the configuration data sent to the client. Overwrite this in child class.
- onError function(error) - To be called in the case of error.
- onSuccess function(alteredConfig) - The function must be called in order for the http response to be sent.
- context Context - See requesthandler-api.js
- config object - Configuration object that will be delivered as the response to the client's getConfig request.
-
onHttpReady() - An event method that is triggered when httpServer is started listening. Overwrite this in child class.
-
onHttpsReady() - An event method that is triggered when httpsServer is started listening. Overwrite this in child class.
-
onOptions(context) - An event method that is triggered when the client sends a request with OPTIONS method. This method fills in the required CORS related response headers. Overwrite this in child class when a different approach is needed.
- context RequestContext - The RequestContext object.
-
onRequest(context) - An event method that is triggered before the actual handling of the request. Overwrite this in child class.
- context RequestContext - The RequestContext object.
-
onResponse( context, params ) - An event method that is triggered the actual sending of the response. Overwrite this in child class.
- context RequestContext - The RequestContext object.
- params.status number - The Http Status code.
- params.headers objects, Http response headrers.
- params.body string/stream.Readable - The content for the response body.
Properties
- apiEntryPoint string - API entry point. Default is "api".
- apiExtensions array (readonly) - Full names of the API extension mofule files to be loaded before the server starts.
- defaultDirectory string - Full path of the root virtual directory.
- defaultDirectoryName string - Name of the root virtual directory.
- defaultDocument string - Default document.
- httpServer http.Server (readonly) - Node.js http.Server object. Property is undefined if the port option is set as 0.
- httpsOptions object (readonly) - Server options as object.
- httpsServer https.Server (readonly) - Node.js https.Server object. Property is undefined if the sslPort option is set as 0.
- logApiRequests boolean - Indicates whether API requests are written in to the log file.
- logFileRequests boolean - Indicates whether file requests are written in to the log file.
- mimeTypes object (readonly) - Includes MIME types the server is supporting.
- port number - http.Server port number .
- root VirtualDirectory (readonly) - Root virtual directory created based on defaultDirectory and defaultDirectoryName properties.
- sslPort number - https.Server port number.
VirtualDirectory class
Initialization
VirtualDirectory objects are initialized by the OKServer and are accessible with the method getVirtaulDirectory or - in case of the root virtual directory - with the property root.
Properties
- defaultDocument string - Name of the default document.
- fullname string - The full name of the directory as it is written in the URL address.
- handler RequestHandler - The request handler associated to the virtual directory.
- handlerName string - The name of the handler associated to the virtual directory.
- name string - Name of the virtual directory.
- path string - Virtual directory path.
- parent VirtualDirectory - Parent virtual directory.
Context class
Initialization
Context objects are initialized by the OKServer's API System and passed to a API services' worker functions as the first parameter (and also as this keyword if the worker function is not an array function).
Properties
- cookies object - Request cookies as an object.
- httpRequest http.IncomingMessage - Request as the node.js IncomingMessage object.
- httpResponse http.ServerResponse - Response as the node.js ServerResponse object.
- onError callback function(Error) - A callback function to be called in the case of error.
- onSuccess callback function(responseContent) - A callback function to be called in the case of success. The responseContent parameter will be assigned as the value of the content property of the API response object.
- request reuest API request object as it is in http request body.
- requestHandler ApiRequestHandler - ApiRequestHandler object.
- requestName string - The name of the request made by a client.
- server OKServer - The instance of OKServer.
- started number - The request time as milliseconds (Date().getTime()).
RequestContext class
Initialization
RequestContext objects are initialized by the OKServer on every client request and passed to the appropriate request handler as the only parameter of the onRequest method.
Properties
- cookies object - Requests cookies.
- handler RequestHandler - Request Handler object.
- handlerName string - Name of the Request Handler serving the request.
- origin string - The content of the request's origin header.
- path string - The path in request URL.
- pathName string - The path in request URL.
- physicalPath string - The full physical path of the virtual directory to which the request URL indicates.
- request http.IncomingMessage - Request as the node.js IncomingMessage object.
- response http.ServerResponse - Response as the node.js ServerResponse object.
- server OKServer - The instance of the OKServer.
- url object - Server's url parsed to the node.js URL object.
- virtualDirectory VirtaulDirectory - The virtual direcory object the request url pathname points to.
Methods
-
isForbidden() -> boolean - Indicates whether the path which the http request is pointing to is forbidden. This method is automaticly called by the server.
- return value: boolean
-
setResponseCookie( cookie, encoder ) - Adds a cookie to the Http response by adding a Set-Cookie header.
- cookie object|array - See OKServer.setResponseCookie()
- encoder function, - See OKServer.setResponseCookie()
-
solveAllowedOrigin() -> string - Returns RequestContext.origin if it is included in the list of allowed origins in the server settings or if the allowed origin setting contains the * character. This method is automaticly called by the server.
- return value: boolean
Module requesthandler
Functions
-
requesthandler.getHandler( handlerName ) - Get the Request Handler object by it's name.
- handlerName string - Name of the handler.
- Return value: object - Request Handler object inherited from RequestHandler.
Properties
- RequestHandler class RequestHandler - The RequestHandler class for the Request Handler inheritance.
RequestHandler class
Initialization
Objects inherit from RequestHandler are instantiated by the OKServer when loadHandler method is called.
Properties
- options object - Shortcut to OKServer.options
- server OKServer - OKServer object.
Methods
-
getRemoteIp( request ) - Shortcut to OKServer.getRemoteIp().
- request http.IncomingMessage
- Return value: string - IP address as string.
-
sendResponse( context, params ) - Sends response to the client.
- context: RequestContext - RequestContext object.
-
params object
- status number - The Http Status code. Default value is 200.
- headers objects - Http response headrers. Default value is {}.
- body string/stream.Readable - The content for the response body. Default value is undefined (means that the response body is not included).
-
setResponseCookie( response, cookies, encoder ) - See OKServer.setResponseCookie()
-
solveMimeName( extension ) - Get MIME Type by file extension.
- extension string - File extension.
- Return value: string - MIME type.
-
onRequest( context ) - OKServer calls this method for every client request addressed to the handler of the method. onRequest should handle sending of a response to the client.
- context RequestContext - RequestContext object.
-
decodeURI( uri )
- uri string - URI string.
- Return value: string - Decoded URI string.