The zero dependency http2 nodejs multithreading framework
SICARII Website
SICARII Dev Wiki
Documentation
- Installation
- About
- Initialization
- build
- server
- sync
- router
- configuration
- stream
- push handler
- headers
- app
- body parser
- etags
- cookie parser
- template engines
- botnet
- ip blacklist
- ip whitelist
- auth-token
- cache
- store
- sessions
- compression
- static file server
- MIME types
- logs
- crypt
- backwards-compatibility
Installation
npm
stable release
$ npm install sicarii --save
dev release
git
$ git clone https://github.com/angeal185/sicarii.git
About
Sicarii is a nodejs http2 framework for projects of all sizes.
- zero dependencies forever
- multithreading by default
- does not need or use the nodejs http2 compatibility layer api but can be extended to do so
- non restrictive design in that you can use the sicarii api or vanilla nodejs most of the time
- easily extendable
Initialization
As sicarii is built for http2, SSL certificates are required. The default path for the ssl certificates is as follows:
./cert/localhost.cert
./cert/localhost.key
These options be edited in the default ./config/config.json
file at config.ssl
.
- for using the
key/cert/pfx/ca
options, a path to the file should be provided as the arg. config.server
accepts all of the same default arguments as nodejs http2 server config.- sicarii will automatically combine
config.ssl
withconfig.server
self signed certificates can be used for development and created as follows:
ECDSA
$ openssl ecparam -name secp384r1 -genkey -out localhost.key$ openssl req -new -x509 -key localhost.key -out localhost.cert -days 365
RSA
$ openssl req -x509 -new -x509 -sha256 -newkey rsa:4096 -nodes -keyout localhost.key -days 365 -out localhost.cert
Build
run the following line of code in any file inside your cwd to build sicarii.
;
Upon first run and if no config file is found, sicarii will attempt to generate the following.
./config
~ default config directory../config/config.json
~ default config file../config/ip_config.json
~ default ip whitelist/blacklist file../render
~ default render/document directory../render/index.html
~ starter html file../static
~ default static file directory../static/css/main.css
~ starter css file../static/modules/main.mjs
~ starter mjs file../uploads
~ default upload directory../logs
~ default logs directory../store/cache
~ default cache write dir../store/session
~ default session write dir../store/store
~ default store write dir.
this action is sandboxed for security reasons. should you wish to, you can delete the associated build files:
/sicarii/build.js
/sicarii/lib/utils/init.js
const app = ; app
Server
Sicarii is built to incorporate multi-threading by default. you can edit your thread count at config.cluster.workers
Although many frameworks wrap the server object within their app, limiting your server actions to those they wish you to have access to, sicarii does not. sicarii extends the existing nodejs modules in place, leaving you full access to the nodejs server object. Most of these extensions can be either disabled, replaced, configured or extended.
sicarii uses the modern nodejs http2 api and does not need or contain any code related to the http2 Compatibility API.
Below is a 30 second minimal rest-api
/static server
example.
const app cluster = ;// app is always called first if clusterisMaster const sync Cache server logs = ; // Cache extentions here ~ if any // server extentions here ~ if any // logs extentions here ~ if any // * spawn workers // * synchronize master/worker communication // * respawn dead workers // * start cache on config.cache.port cache port // * automatically handle cache requests // * automatically handle log requests sync; else const server router crypt = ; // serve static router; // json rest router; //start worker server at config.port server;
server.log_ip()
refer to logs for a detailed explanation
log ip address
/** * @server.log_ip(ip, path) * * @param * @param **/ router;
server.log_history()
refer to logs for a detailed explanation
log history
/** * @server.log_history(data) * * @param **/ router;
server.log_error()
refer to logs for a detailed explanation
log error
/** * @server.log_error(data) * * @param **/ router;
server.pre_cache()
server.pre_cache() will enable you to pre-cache your static files/docs.
- this method can only be called once and upon doing so, it will remove itself
- this method is apart of
sync
although you may have many workers, it will only be called once. - this method is for static files/docs only, it is not intended for rendered docs
config.pre_cache
is the path to your pre_cache config fileconfig.verbose
enabled will log to console the cache status of a streamed file
the configuration file can be configured like so:
/* ./config/pre_cache.json */ "render": "ctype": "text/html" // file content-type 'only' "url": "/index.html" // file path relative to render path "static": "ctype": "text/css" "url": "/css/main.css" // file path relative to static path "ctype": "application/javascript" "url": "/modules/main.mjs"
the method can be called like so:
const app cluster = ; ifclusterisMaster const sync = ; sync; else const server router = ; router; // can be optionally called in chain // sync will ensure the method is only called by first worker server;
server.push_handler()
refer to push handler
server.push_handler() will enable/disable automatic stream push of static files.
- this method takes priority over
config.push_handler.enabled
const app cluster = ; ifclusterisMaster const sync = ; sync; else const server router = ; router; //enable push_handler manually server;
Sync
the sync object is is used to control and synchronize events between master/worker
- sync is optionally responsible for all tasks related to the cluster module
- sync will automatically handle spawning of new worker threads
- sync will automatically handle respawning of crashed worker threads
- sync will automatically handle inter-process messaging across all processes
- sync will automatically initialize Cache and start the cache server
- sync will handle inter-process ip/history/error logging
- sync is a part of the master scope
sync.init()
/** * sync.listen(settings) * @param **/ if clusterisMaster const sync = ; // * spawn workers // * synchronize master/worker communication sync;
sync.respawn()
if clusterisMaster const sync = ; // * respawn dead workers sync // or sync
sync.listen()
/** * sync.listen(callback) * @param **/ if clusterisMaster const sync = ; // * start cache on config.cache.port cache port sync // or sync
sync.kill()
/** * sync.kill(id) * @param **/ if clusterisMaster const sync = ; sync // kill worker with id 1 then worker with id 2 // with sync.respawn() active these workers will be respawned
sync.kill_all()
if clusterisMaster const sync = ; sync // kill all workers // with sync.respawn() active these workers will be respawned
Router
methods
The default allowed router methods can and should be configured at config.stream.methods
.
-
config.stream.methods
accepts all compatible http methods. you should only add the ones you use. -
config.stream.method_body
contains all of the router methods that accept a body. -
config.stream.method_query
contains all of the router methods that accept a query string. -
If you are not using a method in your app, you should remove it to improve both the security and performance of your app.
the router also accepts all of the default nodejs stream methods.
below listed are some basic router method examples:
/** * router[event](path, callback) * @param * @param **/ router; // head streamrouter; // trace streamrouter; // post streamrouter; // delete streamrouter; // patch streamrouter; // put streamrouter; router; // send response headers and render static documentrouter; router; // send response headers and render with optional template engine installedrouter;
Configuration
sicarii has a tiny but powerful list of configurations
the configuration file at ./config/config.json
is an essential part of sicarii.
you MUST tweak it to your own requirements in order to maximize performance and security.
//defaults "port": 8080 // server port "origin": "https://localhost" // server origin "verbose": true // show log to console "dev": true // log errors to console "proxy": false // x-forwarded-for as ip address "ip_config": "/config/ip_config" // path to ip_config.json "pre_cache": "/config/pre_cache" // path to pre_cache.json "push_handler": // automatic push handler "enabled": true "accept": "text/html" // accept header document types to accept "path": "/config/push" // path to push config file "cluster": "workers": 2 // worker count "settings": //worker settings "serialization": "json" "sync": "respawn": true // auto-respawn dead workers "session": "path": "/store/session/db.json" //read/write dir relative to cwd "maxage": 1000000 //maxage of sessions in ms "secret": "" //optional session secret "cache": "url":"https://localhost:5000" // cache server url "timeout": 5000 //cache response timeout ms "proxy": false // x-forwarded-for as ip address "authtoken": //cache auth-token header "enabled": false "header": "X-Authtoken" "token": "12345" "whitelist": //cache server ip whitelist "enabled": true "ip": "::ffff:127.0.0.1" //cache whitelisted ip addersses "server": //cache server config ~ accepts all nodejs http2 server settings "rejectUnauthorized": false "headers": //cache server outbound headers "cookie_parser": "enabled": true //enable cookie parser "auto_parse": true //enable auto cookie parse "sig": "hmac": "secret" // cookie sign hmac "prefix": "sig" // cookie sig prefix "stream": "path_limit": 100 // stream path size limit ~ false to disable check "case_sensitive": true // converts url pathnames to lowercase if false "param_limit": 1000 // stream url search size limit ~ false to disable check "body_limit": 5000 // stream body size limit ~ false to disable check "methods": // add all allowed http methods ~ remove if unused "get" "post" "connect" "put" "delete" "head" "querystring": true // enable stream.qs "method_body": "post" "delete" "patch" "put" // methods return body "method_query": "get""connect" "head" "options" "trace"// methods return query params "content_types": // accepted body content-types ~ remove if unused "application/json" "text/plain" "multipart/form-data" "application/x-www-form-urlencoded" "blacklist": //enable server ip blacklist "enabled": false "msg": "your ip has been blacklisted, have a nice day" // unauth msg "whitelist": //enable server ip whitelist "enabled": false "msg": "Unauthorized" // unauth msg "authtoken": //enable auth token header "enabled": false "header": "X-Authtoken" "token": "xxxxxx" "msg": "server offline" // unauth msg "server": // accepts all http2 nodejs server options "ssl": "cert": "/cert/localhost.cert" // key/cert/pfx/ca as string path to file "key": "/cert/localhost.key" "store": // sicarri store "path": "/store/store/db.json" // read/write path relative to cwd "uploads": "enabled": true "path": "/uploads" // uploads dir, relative to cwd() "recursive": true //enable recursive folder creation "gzip": true // compress file using gzip "brotli": false // compress file using brotli "deflate": false // compress file using deflate "mimetypes": // accepted mimetypes "max_filename": 30 // max filename length "max_filesize": 50000 // max upload content length "static": "path": "/static" // default static file path "blocked": "etag": // etag header "enabled": true // use etags on rendered files "digest": "sha3-256" //etag digest hash ~ crypto.getHashes(); "encode": "base64" //etag digest encoding hex/base64 "cache": // static file server cache "enabled": true // enable cache on static file server "maxage": 1000000 // cached items maxAge "headers": {} // default headers for static file server "render": // render/tempate engine defaults "path": "/render" "blocked": "etag": // etag header "enabled": true // use etags on rendered files "digest": "sha3-256" //etag digest hash ~ crypto.getHashes(); "encode": "base64" //etag digest encoding hex/base64 "cache": // rendered files cache "enabled": true // enable cache on rendered files "maxage": 1000000 // cached items maxAge "headers": // default headers for rendered files "X-Frame-Options": "DENY" "Referrer-Policy": "no-referrer" "Server": "Nodejs" "Access-Control-Allow-Origin": "*" "Access-Control-Allow-Methods": "GET" "X-DNS-Prefetch-Control": "on" "Strict-Transport-Security": "max-age=31536000; includeSubDomains" "X-Content-Type-Options": "nosniff" "X-XSS-Protection": "1" "TK": "N" "compression": "gzip": // gzip compression "enabled": true "prezipped": false // use pre-compressed files "ext": ".gz" // compressed file extention "setting": {} // accepts all nodejs gzip compression settings "brotli": // brotli compression "enabled": false "prezipped": false // use pre-compressed files "ext": ".br" // compressed file extention "setting": {} // accepts all nodejs brotli compression settings "deflate": // deflate compression "enabled": false "prezipped": false // use pre-compressed files "ext": ".dfl" // compressed file extention "setting": {} // accepts all nodejs deflate compression settings "cors": // default stream.cors fallback "origin": '' // string | Access-Control-Allow-Origin "methods": '' // string | Access-Control-Allow-Methods "allow_headers": '' // string | Access-Control-Allow-Headers "expose_headers": ''// string | Access-Control-Expose-Headers "credentials": true // boolean | Access-Control-Allow-Credentials "maxage": 9999 // number | Access-Control-Max-Age "csp": // content security policy object "default": "default-src 'self'" "feature_policy": // feature policy object "default": "microphone 'none'; geolocation 'none'" "logs": "path": "/logs" //path to log dir "separator": "|" // log separator "logs":"error" "history""ip" "cron": 86400000 // logs cronjob interval "console_error": false //log to console log-related errors "compression": "gzip" // backup compression ~ gzip/deflate/brotli "encodeURIComponent": false // encode log entries "error": "enabled": true // enable auto error logs "max_size": 5000 // log max file size "base_name": "error" //log file base name "ext": ".txt" //log file base extension "history": "enabled": true // enable auto history logs "max_size": 5000 // log max file size "base_name": "history" //log file base name "ext": ".txt" //log file base extension "ip": "enabled": true // enable ip logging "max_size": 5000 // log max file size "base_name": "ip" //log file base name "ext": ".txt" //log file base extension "log_time": true // add timestamp to log "log_path": true // add path to log "template_engine": // template engine config "engines": "basic" "poorboy" "nunjucks" "ejs" "pug" "mustache" "twig" "squirrelly" "ect" "eta" "liquidjs" "basic": "enabled": true "settings": "pretty": false "filters": {} "cache": false "squirrelly": "enabled": false "settings": {} "eta": "enabled": false "settings": {} "liquidjs": "enabled": false "settings": "extname": ".liquid" "ect": "enabled": false "settings": "cache": false "open": "<%" "close": "%>" "poorboy": "enabled": false "settings": "use_globals": false "globals": {} "nunjucks": "enabled": false "jinjacompat": true "filters": "" "globals": "enabled": false "vars": {} "settings": "autoescape": true "noCache": true "throwOnUndefined": false "trimBlocks": false "lstripBlocks": false "tags": {} "ejs": "enabled": false "settings": {} "pug": "enabled": false "settings": "pretty": false "filters": {} "cache": false "mustache": "enabled": false "tags": "{{" "}}" "settings": {} "twig": "enabled": false "settings": {} "mimetypes": // a list of all your allowed mimetypes "crypt": "jwt": "secret": "secret" // jwt secret for hmac "digest": "sha256" // jwt digest for hmac "encode": "base64" // jwt encoding "separator": ":" // jwt token separator "header": // jwt header "typ": "JWT" "alg": "HS256" "claims": "iss": "token issuer" // optional jwt issuer "sub": "token subject" // optional jwt subject "aud": "token audience" // optional jwt audience "exp": 5000000 // mandatory ms till expires "nbf": 0 // optional ms till valid "hmac": "secret": "secret" // hmac secret "digest": "sha3-512" // hmac hash function "encode": "hex" // output encode "pbkdf2": "digest": "sha3-512" // hash function "encode": "hex" // output encode "iterations": 50000 // kdf iterations "scrypt": "encode": "hex" // output encode "cost": 16384 // scrypt cost "blockSize":8 // scrypt cost "parallelization": 1 // scrypt parallelization "encryption": "secret": "" // encrypt/decrypt ~ app secret "secret_len": 32 // correct key length "iterations": 60000 // iterations to be used in keygen "digest": "sha3-512" // digest to be used in keygen "settings": // THESE SETTINGS MUST BE VALID "cipher": "aes" // encrypt/decrypt cipher "bit_len": "256" // encrypt/decrypt bit "iv_len": 32 // encrypt/decrypt iv length "tag_len": 16 // encrypt/decrypt auth-tag length "encode": "hex" // encrypt/decrypt/keygen encoding "mode": "gcm" // encrypt/decrypt mode "ecdsa": "curve": "secp521r1" // ecdsa curve "encode": "hex" // ecdsa encoding "hash": "sha3-512" // ecdsa hash used "privateKey": // accepts all nodejs ec privateKey settings "type": "sec1" "format": "der" "publicKey": // accepts all nodejs ec publicKey settings "type": "spki" "format": "der" "ecdh": // ecdh key exchange "curve": "secp521r1" // ecdh curve "encode": "hex" // ecdh encoding "rsa": // rsa encryption "length": 4096 // rsa modulusLength "publicExponent": 65537 "encode": "hex" "oaepHash": "sha512" // rsa oeap hash used "publicKey": // accepts all nodejs rsa publicKey settings "type": "pkcs1" "format": "pem" "privateKey": // accepts all nodejs rsa privateKey settings "type": "pkcs8" "format": "pem" "otp": // contains the one time pad defaults "rounds": 1 // otp encrypt/decrypt rounds count "iterations": 10000 // iteration count for generating a secure pad "digest": "sha512" // digest used for generating a secure pad "encode": "hex" // encoding used for otp "bot": "detect": "items": "Googlebot" // manual detect bots via user-agent sub-string "block": // automatically block bots via user-agent sub-string "enabled": false "msg": "Unauthorized" // bot block msg "items": // blocked bots array
Stream
accepts all nodejs methods and the following:
stream.doc(src, content-type)
stream doc will serve a document from the render folder
- this method will use cache if available
- this method will use compression if available
- this method will stream respond headers
- this method will send default headers from
config.render.headers
- this method will use etag settings from
config.render.etag
- this method will use cache settings from
config.render.cache
- this method will use gzip/brotli/deflate settings from
config.compression
/** * stream.doc(path, contentType, callback) * @param * @param * @param **/ router;
stream.render(src, data)
stream render will serve a rendered document from the render folder. refer to template engines.
- this method will use cache if available
- this method will use compression if available
- this method will stream respond headers
- this method will send default headers from
config.render.headers
- this method will use etag settings from
config.render.etag
- this method will use cache settings from
config.render.cache
- this method will use gzip/brotli/deflate settings from
config.compression
/** * stream.render(path, obj, callback) * @param * @param * @param **/ router;
stream.pushStatic(path, ctype)
stream pushStatic will push a file or files from the static folder before requested.
- this method can be chained to push multiple files
- this method will use cache if available
- this method will use compression if available
- this method will send default headers from
config.static.headers
- this method will use etag settings from
config.static.etag
- this method will use cache settings from
config.static.cache
- this method will use gzip/brotli/deflate settings from
config.compression
config.verbose
will log the push state of a file- this method is asynchronous so the
stream
object is immediately returned - any errors are handled by sicarii in the same manner as the static file server
/** * stream.pushStatic(path, ctype) // single file * @param * @param * * stream.pushStatic(obj) // multiple files * @param **/ router;
stream.download(file, content-type)
stream.download will initiate a file download upon browser navigation.
- stream.download uses
config.static
settings - this method will use cache if available
- this method will use compression if available
- this method will stream respond headers
- this method will send default headers from
config.static.headers
- this method will use etag settings from
config.static.etag
- this method will use cache settings from
config.static.cache
- this method will use gzip/brotli/deflate settings from
config.compression
- this method will Content-Disposition 'attachment; filename="the files name"' to the headers;
/** * stream.download(path, contentType, callback) * @param * @param * @param **/ router;
stream.upload(object, callbabk)
stream.upload will upload a file to your uploads dir if enabled at config.uploads.enable
config.uploads.gzip
will enable/disable gzip compression for uploadsconfig.uploads.brotli
will enable/disable brotli compression for uploadsconfig.uploads.deflate
will enable/disable deflate compression for uploadsconfig.uploads.path
is your upload path relative to cwd()config.uploads.recursive
will enable recursive dir creation withinconfig.uploads.path
,config.uploads.mimetypes
should list all accepted upload mimetypes in the same format asconfig.mimetypes
config.uploads.max_filename
max filename lengthconfig.uploads.max_filesize
max content length
simple upload example:
/** * stream.upload(settings, callback) * @param * @param **/ router;
stream.json(data)
stream.json() performs the following actions:
- add content-type 'application/json' to the headers;
- stream the headers object.
- send stringified json
/** * stream.json(obj, contentType, callback) * @param {array/object} obj // data to be stringified * @param **/ router;
stream.redirect(dest)
stream.redirect() performs the following actions:
- add location destination to the headers;
- stream the headers object.
- send redirect
/** * stream.redirect(path) * @param **/ router;
stream.ip
stream.ip returns the client ip address
- enable config.proxy to return ['x-forwarded-for'] ip
router;
stream.headers
stream.headers will return an object containing all current and default outbound headers;
this is not to be mistaken with the received headers
object;
router
stream.addHeader()
stream.addHeader(key,val) will add a header to stream.headers
/** * stream.addHeader(key, val) * @param * @param **/ router
stream.addHeaders()
stream.addHeaders(obj) will assign an object of headers to stream.headers
/** * stream.addHeaders(key, val) * @param **/ router
stream.cors()
stream.cors() will add the included cors options to stream.headers
- this method will override any default cors headers in
config.render.headers
||config.static.headers
- this method will fallback to
config.cors
if no object is provided
/** * stream.cors(obj) * @param **/ router
stream.ctype()
stream.ctype(val) will add the Content-Type header to stream.headers
/** * stream.ctype(val) * @param **/ router
stream.lang()
stream.lang(val) will add the Content-Language header to stream.headers
/** * stream.lang(val) * @param **/ router
stream.tk()
stream.tk(val) will add the TK header to stream.headers
/** * stream.tk(val) * @param **/ router
stream.csp()
stream.csp(val) will add the Content-Security-Policy header to stream.headers
- stream.csp will load the csp from
config.csp
; - this method enables you to store and use multiple pre-defined content security policies
/** * stream.csp(val) * @param **/ router
stream.feature()
stream.feature(val) will add the Feature-Policy header to stream.headers
- stream.feature will load the Feature-Policy from
config.feature_policy
; - this method enables you to store and use multiple pre-defined feature policies
/** * stream.feature(val) * @param **/ router
stream.status()
stream.status(val) will set the :status header to stream.headers
/** * stream.status(val) * @param **/ router
stream.query
stream.query is part of body parser
. if enabled, it will parse the given query to json.
refer to body parses section.
config.stream.method_query
controls the accepted router methods.config.stream.content_types
controls the accepted content types.
router;
stream.qs
stream.qs is similar to stream.query
but returns the unparsed querystring.
This method is intended for use with custom or complex querystrings;
config.stream.querystring
enable/disable- the returned querystring is decoded with decodeURIComponent()
router;
stream.body.text
stream.body.text is the default body parse format
- returns
string
router;
stream.body.buffer
stream.body.buffer is part of body parser
.
- returns
buffer
router;
stream.body.json
stream.body.buffer is part of body parser
.
refer to body parses section.
- returns
json
for supported content-types
router;
stream.cookies
this method is a part of cookie parser refer to cookie parser
stream.cookie will enable you to easily access all cookies in headers
- this method automatically deserializes all cookies.
- this method requires
config.cookie_parser.enabled
to be enabled - this method can be enabled/disabled at
config.cookie_parser.auto_parse
router
stream.cookie()
this method is a part of cookie parser refer to cookie parser
stream.cookie(name,val,obj) will enable you to easily add cookies to the stream.response
- this method automatically adds the created cookie to
stream.headers
- this method can be enabled/disabled at
config.cookie_parser.enabled
- this method can create a separate signed cookie for tamper detection
config.cookie_parser.sig.secret
is used to hmac the cookieconfig.cookie_parser.sig.suffix
is the signed cookies suffix- a signed cookie will be will use digest/encode settings from
config.crypt.hmac
/** * stream.cookie(key, val, settings) * @param * @param * @param **/ router
push handler
the push handler will enable/disable automatic stream push of static files.
upon stream, the server will search the accepted header for a match in config.push_handler.accepted
and will push your selected files with the document
config.push_handler.enabled
enables this method- this method is for static
files
only e.g js/css/png/jpg - this method is not for rendered/static
documents
e.g html/xhtml/xml - this method is for
GET
requests only. config.push_handler.accepted
should contain therequested paths
content-type e.g text/htmlconfig.push_handler.accepted
should not contain the pushed items content-type e.g text/cssconfig.push_handler.accepted
should only contain document content-types that you useconfig.push_handler.accepted
should be as small as possible- automatic stream push of static files is recommended only for push intensive sites
the push configuration file can be configured like so:
/* ./config/push.json */ "url": "/single_push" // the url path that the file is to be pushed for "ctype": "text/css" // file content-type 'only' "path": "/css/main.css" // file path relative to static path "url": "/multi_push" "items": // push multiple items at same url "ctype": "text/css" "path": "/css/main.css" "ctype": "image/x-icon" "path": "/favicon.ico"
router; router; router;
Headers
the headers object includes the following methods:
headers.all()
headers.all() will return a valid json object containing all received headers
router
headers.get()
headers.get() will return a header from the headers object in nodejs http2 format
/** * headers.get(key) * @param **/ router
headers.is()
headers.is() will return a boolean if the header is equal to the comparison
/** * headers.is(key, val) * @param * @param **/ router
headers.has()
headers.has() will return a boolean if the header exists
- will also return true for header that exists and has a value of false or 0
/** * headers.has(key) * @param **/ router
headers.cookies()
headers.cookies() will return a deserialized cookies json object
router
headers.ctype()
headers.ctype() will return the Content-type header if exists
router
headers.agent()
headers.agent() will return the User-agent header if exists
router
headers.bot()
headers.bot() will return true if the user-agent detected is a bot
config.bot.items
should contain an array of bots to check for- this feature could be used to perform targeted seo optimization
router
headers.encoding()
headers.encoding() will return the accept-encoding header if exists
- the returned value/s will be within a trimmed array
router
headers.lang()
headers.lang() will return the accept-language header if exists
- the returned value/s will be within a trimmed array
router
headers.accept()
headers.accept() will return the accept header if exists
- the returned value/s will be within a trimmed array
router
headers.size()
headers.size() length of the headers object
router
headers.count()
headers.count() will return a count of your total headers
router
App
the app object exists as a bridge between worker/master.
- app must be accessible outside of the worker/master scope
- all methods within app are available to the master and worker threads
- app contains a list of helper functions that might otherwise require dependencies
app.config
app.config gives you access to your current configuration vars throughout your app.
console
app.set()
app.set() will set environmental variables available to the scope in which they are called
/** * app.setEnv(key, val) * @param * @param **/ app; console;// val console;//val
app.env()
app.env() will get environmental variables available from the scope in which they are called
/** * app.env(key) * @param **/ app; console;// val
app.uuid
app.config generates a random uuidv4
console// 4370139d-653c-49eb-933e-a714eec14f69
app.bot()
app.bot() will return true if the user-agent detected is a bot
config.bot.items
should contain an array of bots to check for- this feature could be used to perform targeted seo optimization
- refer to
headers.bot()
router
app.fetch()
the app.fetch method will perform a secure http2 client request to any local or external address.
- app.fetch uses your apps ssl certificate/s to create a secue connection
app.fetch uses body parser to automatically parse responses for the following content-types:
application/json
~ response.json | data as parsed json object/arraymultipart/form-data
~ response.text | data as stringapplication/x-www-form-urlencoded
~ response.text | data as string
all content-types are available as:
*
~ response.text | data as string*
~ response.buffer | data as buffer
/** * app.fetch(obj, callback, timeout) * @param * @param @param **/ /* simple json get example */ let head = 'url': 'https://example_get_url.com' //dest url ':method': 'GET' // fetch method ':path': '/example/path' // fetch path 'Content-Type': 'application/json' // your other headers ... let timeout = 5000 // optional app /* simple post example */ let data = JSON; let head = 'url': 'https://example_post_url.com' //dest url ':method': 'POST' // fetch method ':path': '/example/path' // fetch path 'body': data// fetch body for accepted methods "Content-Type": "application/json" // ... app
app.etag()
refer to stream
for a more detailed explanation.
app.etag can be used to manually create a hashed etag from data that you may use in a stream.
the following digests are supported:
insecure
md5
,md5-sha1
,ripemd160
,rmd160
,sha1
secure
sha224
,sha256
,sha384
,sha512
,sha512-224
,sha512-256
,whirlpool
excessive
sha3-224
,sha3-256
,sha3-384
,sha3-512
,blake2b512
,blake2s256
,shake128
,shake256
/** * app.etag(digest, data, encode) * @param * @param * @param **/ router;
app.digest()
app.digest can be used to manually create a digest from data for the Digest header.
the following prefixes are recommended:
sha-224
,sha-256
,sha-384
,sha-512
the following digests are supported recommended:
sha224
,sha256
,sha384
,sha512
those are the current recommended standards.
you can use any equivalents from the above mentioned in app.etag
if you want to implement your own standard.
/** * app.digest(prefix, encode, data, digest) * @param * @param * @param * @param **/ router;
app.cookie_encode()
refer to stream
for a more detailed explanation.
app.cookie_encode can be used to manually create cookies
/** * app.cookie_encode(key, val, settings) * @param * @param * @param **/ router
app.cookie_sign()
refer to cookie_parser
for a more detailed explanation.
app.cookie_sign can be used to manually create signed cookies
/** * app.cookie_sign(key, val, settings) * @param * @param * @param **/ router
app.cookie_decode()
refer to stream
for a more detailed explanation.
app.cookie_decode can be used to create a deserialized cookies object
/** * app.cookie_decode(key, val, settings) * @param **/ router;
app.cookie_verify()
app.cookie_verify can be used to verify signed cookies
- app.cookie_verify is for signed cookies only
- app.cookie_verify will return true if the cookie is valid
/** * app.cookie_verify(name, obj) * @param * @param **/ router
app.blacklist()
refer to blacklist
app.blacklist can be used add ip addresses to your blacklist
- this action controlled by
sync
- this action will trigger an update of the blacklist cache for all worker threads
- no server restart is required.
/** * app.blicklist(ip) * @param **/ router;
app.whitelist()
refer to whitelist
app.whitelist can be used add ip address to your whitelist
- this action controlled by
sync
- this action will trigger an update of the whitelist cache for all worker threads
- no server restart is required.
/** * app.whitelist(ip) * @param **/ router;
app.gzip
refer to compression
for a more detailed explanation.
gzip compression can be used anywhere via the app.gzip method:
/** * @app.gzip(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//gzipSyncstr = app; //gunzipSyncstr = app; console// test //gzipapp
app.brotli
refer to compression
for a more detailed explanation.
brotli compression can be used anywhere via the app.brotli method:
/** * @app.brotli(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//brotliCompressSyncstr = app; //brotliDecompressSyncstr = app; console// test //brotliCompressapp
app.deflate
refer to compression
for a more detailed explanation.
deflate compression can be used anywhere via the app.deflate method:
/** * @app.deflate(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//deflateSyncstr = app; //inflateSyncstr = app; console// test //deflateapp
app.engine.add()
refer to template engines
extra template engines can be added using app.engine.add
:
sicarii/lib/adapters
will contain your new engine template.config.template_engine
will automatically be updated with your settings
/** * app.engine.add(title, obj, callback) * @param * @param * @param **/ appengine
app.engine.del()
refer to template engines
extra engines can be deleted using app.engine.del
:
sicarii/lib/adapters
will have the adapter removedconfig.template_engine
will automatically remove the engine/s- this action should be called for production to minimize sicarii's size
- this action cannot be undone.
/** * app.engine.del(items, callback) * @param * @param **/ appengine
app.qs()
app.qs will return a serialized query string from valid json object
/** * app.qs(items, sep, eq) * @param * @param * @param **/ var data = test: '%^&*$#hsdacsddf' test2: 2345 console // test=%25%5E%26*%24%23hsdacsddf&test2=2345
app.path()
app.path returns a json object containing the parsed path data
/** * app.path(path) * @param **/ let somepath = app; console // {root: '',dir: 'sicarii/lib',base: 'utils.js',ext: '.js', name: 'utils'} console // utils.js
app.url()
app.url returns a json object containing the parsed url data
/** * app.url(path) * @param **/ let someurl = app; console /* { protocol: 'https:', slashes: true, auth: 'user:pass', host: 'sub.example.com:8080', port: '8080', hostname: 'sub.example.com', hash: '#hash', search: '?query=string', query: { query: 'string' }, pathname: '/p/a/t/h', path: '/p/a/t/h?query=string', href: 'https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash' } */
app.dns.get()
- perform dns lookup
- returns json object containing results
/** * app.dns.reverse(path, cnf, callback) * @param * @param * @param **/ appdns;
app.dns.getService()
- perform dns lookupService
- returns json object containing results
/** * app.dns.getService(path,port,callback) * @param * @param * @param **/ appdns;
app.dns.reverse()
- perform dns reverse
- returns json array containing results
/** * app.dns.reverse(path, callback) * @param * @param **/ appdns
app.encode()
- convert between data encoding
supported conversions
- buffer|utf8|hex|base64|Uint8Array|Uint16Array|Uint32Array|Int8Array|Int16Array|Int32Array
/** * app.encode(data, from, to) * @param * @param * @param **/ let str = 'test string'; // basic encode to bufferapp // utf8 string to buffer // convert betweenstr = app // from utf8 string to base64 str = app // base64 string to hex str = app // hex string to Uint8Array // and so on ...
Body parser
sicarii has its own built in body parser for the following content types:
application/json
multipart/form-data
application/x-www-form-urlencoded
These content types can be enabled/disabled at config.stream.content_types
.
if you are not using it, remove it from config.stream.content_types
to improve both security and performance.
The correct content type headers must be sent with the request.
multipart/form-data
and application/x-www-form-urlencoded
will automatically be parsed to valid json.
for example:
// queryrouter // bodyrouter
All other content types are available as text
or buffer
Etags
sicarii has its own built in configurable in Etag generator.
it provides separate options for render/document
to static
files and can also be manually overridden
or manually added on a per case basis.
- automatic
render/document
Etags can be configured atconfig.render.etag
- automatic
static
file Etags can be configured atconfig.static.etag
- automatic etags will use cache settings from
config.render.cache
orconfig.static.cache
if available - etags support either
base64
orhex
encoding.
the following digests are supported:
insecure
md5
,md5-sha1
,ripemd160
,rmd160
,sha1
secure
sha224
,sha256
,sha384
,sha512
,sha512-224
,sha512-256
,whirlpool
excessive
sha3-224
,sha3-256
,sha3-384
,sha3-512
,blake2b512
,blake2s256
,shake128
,shake256
Etags can be manually added using either an app.etag
or stram.etag
function like so:
/** * stream.etag(digest, data, encode) * @param * @param * @param **/ router;
As etags are hashed from the data being sent, they can also easily double as the Digest header:
router;
Cookie parser
sicarii has its own built in cookie parser.
- the cookie parser can be enabled/disabled at
config.cookie_parser.enabled
- with
config.cookie_parser.auto_parse
enabled, inbound cookies will automatically be parsed to json. - if the cookie parser is disabled, cookies can still be created/parsed through
app.cookie_encode()
/app.cookie_decode()
.
encode cookie
sicarii has two methods for creating serialized cookies.
- this method has support for multiple cookies
- this method can create a separate signed cookie for tamper detection
config.cookie_parser.sig.secret
is used to hmac the cookieconfig.cookie_parser.sig.suffix
is the signed cookies suffix- a signed cookie will be will use digest/encode settings from
config.crypt.hmac
- a signed cookie will be will use digest/encode settings from
config.crypt.hmac
/** * stream.cookie(key, val, settings) * app.cookie(key, val, settings) * @param * @param * @param **/ router
decode cookie
sicarii has three methods for returning a deserialized cookies object
/** * app.cookie_decode(key, val, settings) * @param **/ router;
Template engines
sicarii has the ability to render, cache and compress templates engine templates.
refer to stream.render
for further details
- template engines can be configured at
config.template_engine
- templates are rendered with
stream.render
- templates use settings from
config.render
- templates are compresses if compression is enabled
- templates are cached if
config.render.cache
is enabled - all sicarii template engine adapters are asynchronous.
- automatic error handling is provided for consistency across all engines
- each engines individual error messages are still provided in the callback
/** * stream.render(path, obj, callback) * @param * @param * @param **/ //send headers and rendered doc stream //or // send headers and rendered doc stream
sicarii currently supports the following engines:
default
- default engine, renders html files with javascript template literals included
- the default engine is ideal for single page apps or when you do not require extra features
- the default engine does not require any additional installation
router;
index.html
${title}
poorboy
- renders html from javascript
- write your templates in plain javascript
- poorboy engine does not require any additional installation
- poorboy can be extended to use html parsing modules
- poorboy can be used to render pre-compiled templates from any other engine
- poorboy is fast
router;
basic example
// /render/index.js module `<html> <head> <title></title> </head> <body></body></html>`
advanced example
// /render/index.js const includes = ; //cachedmodule `<html> <head> </head> <body> </body></html>`
// /render/includes.js const includes = moduleexports = '<title>'+ i +'</title>' '<li>'+ i +'</li>' { let ul = '<ul>'; for let x = 0; x < ilength; x++ ul += includes ul += '</ul>'; return ul; }
extended example
// /render/index.jsconst cheerio = ; // cachedconst includes = ; //cached module { const $ = cheerio let test = return $ }
// /render/includes.js const includes = moduleexports = '<html><head><title>'+ i +'</title></head><body></body></html>' '<li>'+ i +'</li>'
nunjucks
- usage of nunjucks requires nunjucks to be pre installed
- do not set nunjucks to cache templates as this will be done by sicarii
config.template_engine.nunjucks.filters
is a path to filters file relative to cwdconfig.template_engine.nunjucks.globals.vars
are added to all renders- refer to nunjucks documentation for further details
router;
index.njk
{{title}}
custom filters can be added like so:
/*"nunjucks": { "enabled": true, "filters": "/path/to/filters.js"}*/ // filters.jsmoduleexports = { return str; }
liquidjs
- usage of liquidjs requires liquidjs to be pre installed
- do not set liquidjs to cache templates as this will be done by sicarii
- refer to liquidjs documentation for further details
router;
index.liquid
{{title}}
squirrelly
- usage of squirrelly requires nunjucks to be pre installed
- do not set squirrelly to cache templates as this will be done by sicarii
- refer to squirrelly documentation for further details
router;
index.html
{{it.title}}
twig
- usage of twig requires twig to be pre installed
- refer to twig documentation for further details
router;
index.twig
{{title}}
ejs
- usage of ejs requires ejs to be pre installed
- do not set ejs to cache templates as this will be done by sicarii
- refer to ejs documentation for further details
router;
index.ejs
<%= title %>
ect
- usage of ect requires ect to be pre installed
- do not set ect to cache templates as this will be done by sicarii
- refer to ect documentation for further details
router;
index.ect
<%= @title %>
eta
- usage of eta requires eta to be pre installed
- do not set eta to cache templates as this will be done by sicarii
- refer to eta documentation for further details
router;
index.eta
<%= it.title %>
pug
- usage of pug requires pug to be pre installed
- do not set pug to cache templates as this will be done by sicarii
- refer to pug documentation for further details
router;
index.pug
html head title #{title}
mustache
-
usage of mustache requires mustache to be pre installed
-
this async adapter is specific to sicarii
-
mustache has 0 dependencies
-
refer to mustache documentation for further details
router;
index.html
{{title}} my name is {{#name}}{{> user}}{{/name}} i am {{#age}}{{> years}}{{/age}} years old
partial_user.html
{{name}}
partial_age.html
{{age}}
extend
sicarii template engines is easily extendable
- note ~ extra template engines are currently being added to sicarii
- template engines can be added or removed
add engine
extra engines can be added using app.engine.add
:
sicarii/lib/adapters
will contain your new engine template.config.template_engine
will automatically be updated with your settings
/** * app.engine.add(title, obj, callback) * @param * @param * @param **/ appengine
extra engines can be manually added the following way:
sicarii/lib/adapters
contains templates that you can use as a base to adapt any template engine.- clone one of the template files and rename it
- edit the cloned file to accept your template engine
- add the template engine to
config.template_engine.engines
using the same cloned files name - duplicate
config.template_engine.default
, rename it, add your settings and enable it. - the file name must be the same ass
config.template_engine[your_file_name]
- the adapters you are not using can be deleted and removed from config for production
an example of how easy it is to add a template engine to sicarii:
// /sicarii/lib/adapters/ejs.js const ejs = config = utils = settings = configtemplate_engineejssettings; module{ ejs;}
you are simply passing your template engines data through
to utils.render_sort
in an async way.
delete engine
extra engines can be deleted using app.engine.del
:
sicarii/lib/adapters
will have the adapter removedconfig.template_engine
will automatically remove the engine/s- this action should be called for production to minimize sicarii's size
- this action cannot be undone.
/** * app.engine.del(items, callback) * @param * @param **/ appengine
Botnet
sicarii has its own built in bot detect and block features
- block unwanted bots from accessing data.
- create targeted seo responses for search engines.
bot block
- bot blocking can be configured at
config.bot.block
- bot user-agent sub-strings can be manually added to
config.bot.block.items
config.bot.block.enabled
will enable blocking of all bot user-agent sub-string matches withinconfig.bot.block.items
bot detect
- bot detection can be configured at
config.bot.detect
- bot user-agent sub-strings can be manually added to
config.bot.detect.items
router
Ip blacklist
sicarii has its own built in ip blacklist
- the ip blacklist can be configured at
config.blacklist
- the ip blacklist is controlled by
sync
- ip addresses can be manually added to
./config/ip_config.json
- dynamically adding a blacklist via
app.blacklist
will sync across all worker threads - ip addresses that have been blacklisted will be denied access globally to all worker servers
/** * app.blicklist(ip) * @param **/ router;
Ip whitelist
sicarii has its own built in ip whitelist for both master and worker servers
- the ip whitelist can be configured at
config.whitelist
for workers - the ip whitelist can be configured at
config.cache.whitelist
for the master server - ip addresses can be manually added to
./config/ip_config.json
- ip addresses that have not been whitelisted will be denied access to the master/worker servers
- this feature should be enabled for production on the master server
const app = ; app
Auth-token
sicarii has its own built in header auth-token authentication for both master and worker servers
- the auth-token can be configured at
config.authtoken
for workers - the auth-token can be configured at
config.cache.authtoken
for the master server - streams that do not have the correct auth-token header will be denied access to the master/worker servers
- this feature should be enabled for production on the master server
Cache
sicarii has its own built in easily extendable and multi-thread compatible in-memory cache.
- the same cache is shared over all worker-threads to prevent cache duplication.
- the cache can act as a standalone app for remote usage.
- the cache supports auth-token and ip authentication for local or remote access.
- the cache can be hosted locally or remotely.
- the cache will store compressed streams if either of
gzip/brotli/deflate
are enabled. render/document
cache can be configured atconfig.render.cache
- the
render/static
cache will store headers as well as the document. - the
render/static
cache will automatically remove items dated past their maxage settings. static
file cache can be configured atconfig.render.static
.- if
config.verbose
is enabled, the cache status of a render/doc/file... will be logged to console. - the cache module MUST be initiated outside of the worker scope.
- not doing so would would pointlessly spawn multiple instances of the cache.
- one instance of cache shares data with all instances of workers.
- cache has its own
server
object that has been named the same as your appsserver
help to prevent spawning both on the same thread. - the cache server can be configured at
config.cache
. - the cache port can be set at
config.cache.port
config.cache.server
accepts all nodejs http2 configuration
authentication
the cache server can be authenticated by way of auth-token and/or ip whitelist
- the ip whitelist
config.cache.whitelist
will limit access to the ip addresses inconfig.cache.whitelist.ip
- the ip authtoken
config.cache.authtoken
will require the specified token header and secret upon connection.
usage
below is one
example of a correct
way and an incorrect
way to setup cache.
const app cluster = ; ifclusterisMaster /* CORRECT! */ const sync Cache server = ; // cache extensions here // start cache server manually server // or // start cache server with sync sync; else const server router = ; /* INCORRECT! */ const server = ; // server server
cache object
the cache has the following collections which are reserved
for sicarii internal usage.
"render": // render/document cache "static": // static cache "session": // session cache "store":
cache internal methods
the cache has the following Methods which are reserved
for sicarii internal usage.
you may use these but should not change them:
/** * @param * @param **/ // used to add an object within to a collectionCache;// Cache.add_cache('store', {key: 'val'}); // used to find an object within a collectionCache; //used to delete an object by index from a collectionCache //used to reset a collectionCache //used to import a collectionCache //used to export a collection to fileCache
cache extend
- the cache server does not share the same nodejs method extensions as your app server.
the Cache and server objects can be easily extended to add your own methods like so:
ifclusterisMaster const sync Cache server = ; /* add to the Cache object */ //return a collection Cacheprototype{ return thiscollection; } //add a new collection Cacheprototype{ thiscollection = objnew_name; return this; } //add a new object to a collection Cacheprototype{ thiscollection return this } /* add to or extend the caches server object */ //add custom error handler to cache server. server //extend on listening to include extra data. server // all extensions should be added prior to starting server // server.listen / sync.listen will create the new Cache() object //server.listen() sync;
cache api
the cache can be accessed via either or both of the server/browser depending on your settings.
/* api object */ let cache_obj = method: 'val' //the cache method to use src: 'static' // the collection name data: //the data object with settings/data specific to the method if any.
cache http2 client request using app.fetch
/* app.fetch example */ let head = 'url': appconfigcacheurl //dest url ':method': 'POST' // fetch method ':path': '/' // fetch path 'Content-Type': 'application/json' 'X-Auth-Token': 'secret' 'body': JSON// fetch body for accepted methods app
cache http2 client request
/* server example */ const http2 = ; let options = app; options = Object; client = http2head = ':method': 'POST' ':path': '/' 'Content-Type': 'application/json' 'X-Auth-Token': 'secret'stream = clientbody = ''; stream; stream; stream; stream; // send api objectstream;
cache Browser fetch request
/* browser example */
Store
sicarii has its own built in easily extendable and multi-thread compatible in-memory/flat-file json store.
- the same store is shared over all worker-threads.
- store is built into the Cache object
- store supports auth-token and ip authentication for local or remote access.
- store can be hosted locally or remotely.
- store is initiated with Cache.
- a current timestamp is added to every new store object automatically
- store is accessed via the
app
object - store is available to the master and worker scopes
- store items must have a unique id
store api
- the store api is similar to the session api, with a few extra methods
/** * app.store(method, data, callback) * @param * @param * @param **/ let obj = id: app user: 'test' token: 'secret' age 5 // add or update a store object with the same id// a date timestamp is automatically added// adds object to end of collectionapp; // unshift or update a store object with the same id// a date timestamp is automatically added// adds object to beginning of collectionapp; // find a store objectapp; // find the index of a store object// returns -1 for not foundapp; // replace or add additional values to a store objectapp; // assign values to each included key of each object in storeapp; // delete keys from each object in storeapp; // return chunked section of store// app.store('chunk', ['chunk size', 'chunk count'])app; // sort store by key and return count amount// count is optionalapp; // delete a store objectapp; // get the first x amount of store objectsapp; // get the last x amount of store objectsapp; // return filtered store objects by values greater thanapp; // return filtered store objects by values less thanapp; // return filtered store objects by values greater than or equal toapp; // return filtered store objects by values less than or equal toapp; // return store collectionapp; //add multiple objects at the same timeapp; // save store to file at config.store.path// file write is non blockingapp; // load store into cache from config.store.path// this action should only be called onceapp;
store extend
the store object can be easily extended via the Cache object to add your own methods like so:
ifclusterisMaster const sync Cache = ; // Cache.store_[YOUR METHOD NAME] // create function to reset store Cacheprototype{ //src = 'store' //obj = data thissrc = ; return success: true msg: 'store reset' } // start app sync; // reset sessions app
Sessions
sicarii has its own built in easily extendable and multi-thread compatible in-memory session store.
- the same sessions are shared over all worker-threads.
- sessions is built into the Cache object
- sessions supports auth-token and ip authentication for local or remote access.
- sessions can be hosted locally or remotely.
- sessions is initiated with Cache.
- a current timestamp is added to every new session object automatically
- sessions are accessed via the
app
object - sessions are available to the master and worker scopes
- session items must have an unique id
session api
- the session api is similar to the store api, with a few exclusions
/** * app.session(method, data, callback) * @param * @param * @param **/ let obj = id: app user: 'test' token: 'secret' age 5 // add or update a session object with the same id// a date timestamp is automatically added// adds object to end of collectionapp; // unshift or update a session object with the same id// a date timestamp is automatically added// adds object to beginning of collectionapp; // find a session object or automatically delete expired sessionapp; // find the index of a session object// returns -1 for not foundapp; // replace or add additional values to a session objectapp; // assign values to each included key of each object in sessionsapp; // delete keys from each object in sessionsapp; // return chunked section of session// app.session('chunk', ['chunk size', 'chunk count'])app; // sort session by key and return count amount// count is optionalapp; // delete a session objectapp; // get the first x amount of sessionsapp; // get the last x amount of sessionsapp; // return filterd sessions by values greater thanapp; // return filterd sessions by values less thanapp; // return filtered sessions by values greater than or equal toapp; // return filterd sessions by values less than or equal toapp; // return session collectionapp; // remove all expired sessionsapp;
session extend
sessions can be easily extended via the Cache object to add your own methods like so:
ifclusterisMaster const sync Cache = ; // Cache.store_[YOUR METHOD NAME] // create function to reset sessions Cacheprototype{ thiscollection = ; return success: true msg: 'sessions reset' } // start app sync; // reset sessions app
Compression
sicarii has built in support for gzip, brotli and deflate compression.
- automatic compression can be enabled/disabled individually for your render/static/upload/download/cache data.
- the static file server stream pre-compressed files if
config.compression[*].prezipped
is enabled - uncompressed originals are not required to be stored if using
config.compression[*].prezipped
gzip
config.compression.gzip.enable
will enable/disable gzip compressionconfig.compression.gzip.settings
will enable you to configure gzip compressionconfig.compression.gzip.settings
accepts all nodejs gzip settingsconfig.compression.gzip.prezipped
will enable you to load/serve already compressed files- with
config.compression.gzip.prezipped
enabled, you do not have to store an uncompressed copy of the data config.compression.gzip.ext
will set the default gzip file extension
gzip compression can also be used anywhere via the app.gzip method:
/** * @app.gzip(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//gzipSyncstr = app; //gunzipSyncstr = app; console// test //gzipapp
brotli
config.compression.brotli.enable
will enable/disable brotli compressionconfig.compression.brotli.settings
will enable you to configure brotli compressionconfig.compression.brotli.settings
accepts all nodejs brotli settingsconfig.compression.brotli.prezipped
will enable you to load/serve already compressed files- with
config.compression.brotli.prezipped
enabled, you do not have to store an uncompressed copy of the data config.compression.brotli.ext
will set the default brotli file extension
brotli compression can also be used anywhere via the app.brotli method:
/** * @app.brotli(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//brotliCompressSyncstr = app; //brotliDecompressSyncstr = app; console// test //brotliCompressapp
deflate
config.compression.deflate.enable
will enable/disable deflate compressionconfig.compression.deflate.settings
will enable you to configure deflate compressionconfig.compression.deflate.settings
accepts all nodejs deflate settingsconfig.compression.deflate.prezipped
will enable you to load/serve already compressed files- with
config.compression.deflate.prezipped
enabled, you do not have to store an uncompressed copy of the data config.compression.deflate.ext
will set the default deflate file extension
deflate compression can also be used anywhere via the app.deflate method:
/** * @app.deflate(data, method, options, callback) * * @param {Buffer/TypedArray/DataView/ArrayBuffer/string} data * @param * @param * @param **/ let str = 'test'//deflateSyncstr = app; //inflateSyncstr = app; console// test //deflateapp
Static file server
sicarii has its own built in static file server
-
the static file server can be configured at
config.static
-
the static file server stream pre-compressed files if
config.compression[*].prezipped
is enabled -
uncompressed originals are not required to be stored if using
config.compression[*].prezipped
-
the static file server will use and cache compressed files if compression is enabled
-
config.static.path
is the static file dir relative to cwd() -
config.static.blocked
an array of paths to forbid static file server only access -
config.static.etag
static file server etag options -
config.static.headers
default headers to use for all static files -
config.static.cache
enable static file cache -
config.static.cache
enable static file cache -
the static file server will only serve content-types included at
config.mimetypes
MIME types
sicarii uses a strict MIME type policy
sicarii will only allow access to content-types listed at config.mimetypes
sicarii will only allow uploads to content-types listed at config.uploads.mimetypes
- these lists should ONLY include content-types that you use
- shorter lists will increase the speed and security of your app
Logs
sicarii has its own built in extendable logging system
-
config.logs.path
is the logs file dir relative to cwd() -
config.logs.separator
is the separator used to separate log entries -
config.logs.error
will enable logging logger errors to console -
config.logs.compression
the compression type to use for backup of full log files -
all log files have a max size. when reached, the log file is backed up then reset
-
all logging is asynchronous and controlled by
sync
-
all logs use fs.appendFile for speed
logging is optionally provided for the following:
ip logger
will log all ip addresses to file
config.logs.ip.base_name
the base name for the log fileconfig.logs.ip.max_size
the max size for log file before it is backed up and resetconfig.logs.ip.ext
the filename extensionconfig.logs.ip.log_time
adds additional timestamp to logconfig.logs.ip.log_path
adds additional path to log- the ip logger will not log static file streams
- the ip logger will not log streams resulting in an error
ip logger can also be used via server.log_ip() in the worker threads:
router;
error logger
will log all errors to file
config.logs.error.base_name
the base name for the log fileconfig.logs.error.max_size
the max size for log file before it is backed up and resetconfig.logs.error.ext
the filename extension
error logger can also be used via server.log_error() in the worker threads:
router;
history logger
will log all visits to file
config.logs.history.base_name
the base name for the log fileconfig.logs.history.max_size
the max size for log file before it is backed up and resetconfig.logs.history.ext
the filename extension- the history logger will not log static file streams
- the history logger will not log streams resulting in an error
history logger can also be used via server.log_history() in the worker threads:
router;
logs.backup()
logs can be backed up manually via logs.backup()
- this action will compress, backup and reset a log file that exceeds its configured max_size setting
/** * logs.backup(method, callback) * @param * @param **/ ifclusterisMaster const sync logs = ; sync; logs
logs.cron()
logs can be backed up automatically via logs.cron()
- this action will call logs.backup for each log file.
config.logs.cron
will set the cron interval.- this action will compress, backup and reset a log file that exceeds its configured
max_size
setting
ifclusterisMaster const sync logs = ; sync; logs
Crypt
sicarii has its own built in crypto utilities
- crypt is part of the worker scope
const crypt = ;
crypt.rnd()
create random bytes
/** * @crypt.rnd(data, secret, callback) * * @param * @param **/ const server router crypt = ; let randombytes = crypt; console;
crypt.hmac
crypt.hmac can be used to sign or validate data using a hmac
config.crypt.hmac
contains a list of default options which must be valid to nodejs
crypt.hmac.sign()
/** * @crypt.hmac.sign(data, secret) * * @param * @param **/ const server router crypt = ; let sig = crypthmac; console
crypt.hmac.verify()
/** * @crypt.hmac.verify(data, sig, secret) * * @param * @param * @param **/ const server router crypt = ; let sig = crypthmac; console // true
crypt.pbkdf2()
crypt.pbkdf2 provides a sync/async Password-Based Key Derivation Function 2 implementation
config.crypt.pbkdf2
contains a list of default options which must be valid to nodejs
/** * @crypt.pbkdf2(secret, salt, len, callback) * * @param * @param * @param * @param **/ const server router crypt = ; // sync let res = crypt; console // async crypt;
crypt.scrypt()
crypt.scrypt provides a sync/async Password-Based Key Derivation Function implementation
config.crypt.scrypt
contains a list of default options which must be valid to nodejs
/** * @crypt.scrypt(secret, salt, len, callback) * * @param * @param * @param * @param **/ const server router crypt = ; // sync let res = crypt; console // async crypt;
crypt.jwt
crypt.jwt can be used to generate or verify json web tokens
-
config.crypt.jwt
contains a list of default options which must be valid to nodejs -
config.crypt.jwt.encode
use hex/base64 encoding for jwt -
config.crypt.jwt.secret
is the secret used to hmac your jwt data -
config.crypt.jwt.digest
valid nodejs digest to use -
config.crypt.jwt.header
jwt header includes -
config.crypt.jwt.claims
jwt public claims -
you can add extra default plublic claims to
config.crypt.jwt.claims
-
config.crypt.jwt.claims.exp
is amandatory
time till expires in milliseconds -
config.crypt.jwt.claims.nbf
is aoptional
time before valid in milliseconds -
config.crypt.jwt.claims.exp
is mandatory, all other added are optional -
config.crypt.jwt.claims.iat
is automatically generated
crypt.jwt.sign()
/** * @crypt.jwt.sign(data, callback) * * @param * @param **/ const server router crypt = ; // optional private claims ~ empty object for no extra claims {} let jwt_private = name: 'some name' age: 999 // sync let sig = cryptjwt console // returns valid jwt || null for error // async cryptjwt
crypt.jwt.verify()
/** * @crypt.jwt.verify(sig, callback) * * @param * @param **/ const server router crypt = ; // optional private claims ~ empty object for no extra claims {} let jwt_private = name: 'some name' age: 999 sig = cryptjwt; // test jwt //sync console // returns null for error || false for invalid, expired or nbf || jwt obj for pass //async cryptjwt
encryption (symmetric)
-
encrypt/decrypt settings can be configured at
config.encryption
-
config.encryption.modes
includesgcm|cbc|ccm|ctr|cfb|cfb1|cfb8|ocb|ofb
-
config.encryption.cipher
includesaes|aria|camellia
-
config.encryption.bit_len
includes128|192|256
-
config.encryption.iv_len
is the accepted iv length for your options -
config.encryption.tag_len
is the accepted auth-tag length for your mode | if needed -
config.encryption.encode
encoding of your secret and encrypted data -
be aware that most of the different modes require you to alter other options.
crypt.keygen()
create an encryption key to be used for symmetric encryption and decryption
-
config.encryption.secret_len
the correct key length for your encryption -
config.encryption.iterations
pbkdf2 iterations for creating secure key -
config.encryption.digest
hash digest used for creating secure key -
config.encryption.settings.encode
encoding for key/encryption -
a generated key can be manually added to
config.encryption.secret
for access viaapp.config
const server router crypt = ; let secret = crypt; console;
crypt.encrypt()
encrypt data
/** * @crypt.encrypt(data, secret, callback) * * @param * @param * @param **/ const server router crypt = ; let data = 'test' // data to be encrypted secret = crypt; // generate new secure encryption key // sync let ctext = crypt; console // encrypted data || undefined if error //async crypt;
crypt.decrypt()
decrypt encrypted data
/** * @crypt.decrypt(data, secret, callback) * * @param * @param * @param **/ const server router crypt = ; let data = 'test' secret = crypt ctext = crypt; // encrypted data //synclet ptext = crypt;console// test || undefined for error //async crypt;
encryption (asymmetric)
config.rsa.length
the rsa modulusLength 2048|4096|8192|16384config.rsa.publicExponent
default 65537config.rsa.oaepHash
hash digest used for rsa-oaep encryptionconfig.rsa.encode
encoding for key/encryption hex|base64config.rsa.publicKey
accepts all valid nodejs rsa publicKey settingsconfig.rsa.privateKey
accepts all valid nodejs rsa privateKey settings
crypt.rsa.create
create an encryption key pair to be used for asymmetric rsa-oaep encryption and decryption
/** * @crypt.rsa.create(callback) * @param **/ const crypt = ; // generate keypair for rsa-oaep cryptrsa
crypt.rsa.encrypt
encrypt data using rsa-oaep encryption
/** * @crypt.rsa.encrypt(publicKey,ptext,callback) * @param * @param * @param **/ const crypt = ; // generate keypair for rsa-oaep cryptrsa
crypt.rsa.decrypt
decrypt data using rsa-oaep encryption
/** * @crypt.rsa.decrypt(privateKey,ctext,callback) * @param * @param * @param **/ const crypt = ; // generate keypair for rsa-oaep cryptrsa
crypt.ecdsa
config.crypt.ecdsa
contains the ecdsa defaultsconfig.crypt.ecdsa.curve
is the ecdsa curve usedconfig.crypt.ecdsa.encode
is the encoding used for input and outputconfig.crypt.ecdsa.hash
is the hash used to sign dataconfig.crypt.ecdsa.publicKey
accepts all nodejs ecdsa publicKey optionsconfig.crypt.ecdsa.privateKey
accepts all nodejs ecdsa privateKey options
crypt.ecdsa.create()
create elliptic curve keypair
/** * @crypt.ecdsa.create(callback) * * @param **/ const server router crypt = ; // generate ec keypair async cryptecdsa
crypt.ecdsa.sign()
create elliptic curve signature
/** * @crypt.ecdsa.sign(privateKey, data, callback) * * @param * @param * @param **/ const server router crypt = ; // generate ecdsa keypair async cryptecdsa
crypt.ecdsa.verify()
verify data integrity
/** * @crypt.ecdsa.verify(publicKey, sig, data, callback) * * @param * @param * @param * @param **/ const server router crypt = ; let data = 'test data' // generate ec keypair async cryptecdsa
crypt.ecdh
Elliptic Curve Diffie-Hellman (ECDH) key exchange
config.crypt.ecdh
contains the ecdh defaultsconfig.crypt.ecdh.curve
is the ecdh curve usedconfig.crypt.ecdh.encode
is the encoding used for input and output
crypt.ecdh.create()
create ecdh keypair
/** * @crypt.ecdh.create(callback) * * @param **/ const server router crypt = ; // generate ecdh keypair async cryptecdh // generate ecdh keypair sync console
crypt.ecdh.compute()
compute ecdh secret
/** * @crypt.ecdh.compute(privateKey, publicKey, callback) * @param * @param * @param **/ const server router crypt = ; // generate ecdh keypair async cryptecdh
crypt.otp
one time pad (OTP)
config.crypt.otp
contains the otp defaultsconfig.crypt.otp.iterations
is the iteration count for generating a secure padconfig.crypt.otp.digest
is the digest used for generating a secure padconfig.crypt.otp.rounds
is the encrypt/decrypt rounds countconfig.crypt.otp.encode
is the encoding used for input of decryption, output of encryption and the pad.- the pad created must be at least the length of the text to be encrypted
crypt.otp.pad()
generate pad ofor OTP encryption
/** * @crypt.otp.pad(len, callback) * @param * @param **/ const server router crypt = ; let data = 'test' // generate pad to be used cryptotp
crypt.otp.encrypt()
encrypt data using generated pad
/** * @crypt.otp.encrypt(data, key, callback) * @param * @param * @param **/ const server router crypt = ; let data = 'test' cryptotp
crypt.otp.decrypt()
decrypt data using generated pad and ciphertext
/** * @crypt.otp.decrypt(data, key, callback) * @param * @param * @param **/ const server router crypt = ; let data = 'test' cryptotp
Backwards compatibility
http2 is supported as far back as the now obsolete
internet explorer 11 so most people should not
need to worry about Backwards compatibility.
sicarii does however support Backwards compatibility, should you have any need for requiring it.
config.server.allowHTTP1
will enable/disable Backwards compatibility.- the server
stream
event is reserved for http2, but the serverrequest
event is not and will not ever be required by sicarii. - the server
stream
event will always ignore all non http2 requests. - the
request
event will enable you to accept http1 requests using the nodejs http compatibility layer. - sicarii
stream
methods are not supported when using the http2 compatibility layer. - the
request
event is limited to methods in the nodejs http compatibility api but can be manually extended to mimic most of thestream
events.
const app cluster = ; ifclusterisMaster const sync = ; //access to server object and cache prototype sync; else const server router crypt = ; server