This repository has been archived on 2024-09-12. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs-website/source/docs.md

1814 lines
84 KiB
Markdown
Raw Permalink Normal View History

2024-03-15 21:53:12 +01:00
---
title: SVR.JS documentation
excerpt: The SVR.JS documentation provides comprehensive information and instructions on how to use and configure the SVR.JS web server. This documentation is a valuable resource for developers looking to implement and optimize server-side web applications.
date: 2023-12-21 17:10:14
layout: docs-page
---
* * *
**Welcome to the official documentation of SVR.JS!**
_This documentation is in the public domain._
## First use
### System requirements
#### Minimum
* Node.JS 8.4.0 or newer (SVR.JS 3.4.x and earlier), Node.JS 10.0.0 or newer (SVR.JS 3.5.x and later) / Latest version of Bun (experimental).
* OS supported by Node.JS/Bun.
#### Recommended
* Latest Node.JS LTS version.
* 2-core CPU or better.
* 1.5GB of RAM or more.
* One of tested platforms: Android, FreeBSD, GNU/Linux, Haiku, Oracle Solaris, Microsoft Windows.
### Installation
#### Using SVR.JS installer (installer packages made in April 5, 2024 and later; GNU/Linux only)
The command for SVR.JS installation is available in [the SVR.JS home page](https://svrjs.org). First off, switch to _GNU/Linux_ tab, then copy the command below the tab into the terminal. The command looks something like this: `curl -fsSL https://downloads.svrjs.org/installer/svr.js.installer.linux.20240509.sh > /tmp/installer.sh && sudo bash /tmp/installer.sh`. After starting the installer, you will be prompted to select the type of SVR.JS installation. After selecting the type, SVR.JS installer will install Node.JS, SVR.JS and create SVR.JS service. During installation, you may be prompted for the installation of dependencies. Once the installation is done, the server is started at _http://localhost_.
File structure will look like this:
* _/usr/lib/svrjs_ - SVR.JS installation directory
* _/var/log/svrjs_ - SVR.JS logs
* _/var/www/svrjs_ - SVR.JS web root
* _/etc/svrjs-config.json_ - SVR.JS configuration file (SVR.JS _config.json_)
SVR.JS installer will also install these commands:
* _svrjs-loghighlight_ - SVR.JS log highlighter
* _svrjs-logviewer_ - SVR.JS log viewer
* _svrpasswd_ - SVR.JS user management tool
* _svrjs-updater_ - SVR.JS updater
#### Using SVR.JS installer (installer packages made before April 5, 2024; GNU/Linux only)
2024-03-15 21:53:12 +01:00
SVR.JS now has a brand new installer for GNU/Linux. First, [download SVR.JS installer](https://downloads.svrjs.org/installer), then unpack your SVR.JS installer zip archive. After unpacking the installer, download SVR.JS zip archive (not installer), copy it to the installer directory and rename it to "_svrjs.zip_". Then run SVR.JS installer using `sudo bash installer.sh`. After starting the installer, you will be prompted to select the type of OS (type of GNU/Linux distribution). After selecting the type, SVR.JS installer will install Node.JS, SVR.JS and create SVR.JS service. During installation, you may be prompted for the installation of dependencies. Once the installation is done, restart your server OS or type `systemctl start svrjs` or `/etc/init.d/svrjs start` to start SVR.JS and get a web server on _http://localhost_.
File structure will look like this:
* _/usr/lib/svrjs_ - SVR.JS installation directory
* _/var/log/svrjs_ - SVR.JS logs
* _/var/www/svrjs_ - SVR.JS web root
* _/etc/svrjs-config.json_ - SVR.JS configuration file (SVR.JS _config.json_)
SVR.JS installer will also install these commands:
2024-03-15 21:53:12 +01:00
* _svrjs-loghighlight_ - SVR.JS log highlighter
* _svrjs-logviewer_ - SVR.JS log viewer
* _svrpasswd_ - SVR.JS user management tool
#### Using _create-svrjs-server_ tool
To install SVR.JS using _create-svrjs-server_, first install the utility using `npm install -g svrjs`. Then create a directory, which will contain SVR.JS. Change your working directory to a new one, and run one of those commands:
* `create-svrjs-server lts` - Latest SVR.JS LTS version
* `create-svrjs-server latest` - Latest SVR.JS version
* `create-svrjs-server 3.6.1` - SVR.JS 3.6.1 (replace 3.6.1 with your desired version)
After downloading and installing SVR.JS to your working directory, run `node svr.js` for SVR.JS 3.x or `node svr_new.js` for earlier versions or `bun run svr.js` if you're using Bun instead of Node.JS.
You will then see this message:
```
Decompressing modules...
Deleting SVR.JS stub...
Decompressing SVR.JS...
Restart SVR.JS to get server interface.
```
After running this command again, you'll get a web server on _http://localhost_.
2024-05-08 13:51:36 +02:00
#### Using Docker
To install SVR.JS via Docker, first pull the image using `docker pull svrjs/svrjs` command, or `docker pull svrjs/svrjs:lts` command, if you wish to install LTS version of SVR.JS. Then create and start the Docker container using `docker run --name mysvrjs -d -p 80:80 --restart=always svrjs/svrjs` command (replace `mysvrjs` with desired Docker container name). The file structure is the same, as it would be installed via SVR.JS installer. Once the installation is done, the server is started at _http://localhost_.
2024-03-15 21:53:12 +01:00
#### Manual installation
To install SVR.JS manually, first unpack your SVR.JS zip archive you downloaded from SVR.JS download page. Then change your working directory to one containing SVR.JS script stub, and run `node svr.js` for SVR.JS 3.x or `node svr_new.js` for earlier versions or `bun run svr.js` if you're using Bun instead of Node.JS.
You will then see this message:
```
Decompressing modules...
Deleting SVR.JS stub...
Decompressing SVR.JS...
Restart SVR.JS to get server interface.
```
After running this command again, you'll get a web server on _http://localhost_, which looks like this:
![SVR.JS console](/img/svrjs-console.png)
#### After installation
When you visit `localhost`, the page will look like this:
![SVR.JS running for first time](/img/svrjs-firsttime.png)
If you see this page, then SVR.JS installation is successful. You can now replace default server pages (_index.html_, _tests.html_, _licenses_, _serverSideScript.js_) with custom ones, and remove default mods! If you don't see this page, then there was a problem when installing SVR.JS.
### Features
#### Static file handling
* Static file serving (even above 2GB)
* Directory listing serving
* Protection against path traversal
2024-05-13 18:12:03 +02:00
* Content-Range support (for non-HTML static files; also for HTML files from SVR.JS 3.15.1)
2024-03-15 21:53:12 +01:00
* Serving from web root different than SVR.JS installation directory
#### Security
* HTTPS support
* HTTP/2 support
* Built-in block list
* Protection against HTTP authentication brute force attacks (from SVR.JS 3.4.8; enabled by default)
* Ability to hide server version
* OCSP stapling support (from SVR.JS 3.4.9)
#### Configuration and customization
* Configurability via _config.json_ file
* Expandability via server-side JavaScript and mods
* Ability to serve non-standard error pages
* URL rewriting engine
* Event driven architecture powered by Node.JS, along with clustering.
#### Compression and content delivery
* Brotli, gzip and Deflate HTTP compression (Brotli supported since SVR.JS 3.4.11)
* SNI (Server Name Indication) support
* ETag support (from SVR.JS 3.6.1)
* Reverse proxy functionality (requires reverse-proxy-mod SVR.JS mod)
2024-04-14 17:28:43 +02:00
* Forward proxy functionality (requires forward-proxy-mod SVR.JS mod)
2024-03-15 21:53:12 +01:00
#### Authentication and access control
* HTTP basic authentication
#### Gateway interfaces
* CGI (Common Gateway Interface) support (requires RedBrick mod)
* SCGI (Simple Common Gateway Interface) support (requires OrangeCircle mod)
* JSGI (JavaScript Gateway Interface) support (requires YellowSquare mod)
* PHP support (PHP-CGI with RedBrick mod or PHP-FPM with GreenRhombus mod)
#### Additional functionality
* Logging
* Ability to display IP addresses, from which originally request was made (from reverse proxies; via X-Forwarded-For)
### SVR.JS files
* _svr.js_ - main SVR.JS script
* _config.json_ - SVR.JS configuration file
* _serverSideScript.js_ - server-side JavaScript
* _mods_ - directory, from which SVR.JS loads mods
* _log_ - directory, to which SVR.JS logs
* _temp_ - temporary directory for SVR.JS
### SVR.JS utilities
SVR.JS 3.0.0 and later comes with several utilities:
* _logviewer.js_ - SVR.JS log viewing tool
* _loghighlight.js_ - SVR.JS log highlighting tool
* _svrpasswd.js_ - SVR.JS user management tool
### SVR.JS commands
SVR.JS comes with a console interface that provides several built-in commands for managing the server and interacting with it.
Available commands:
* _close_ - Closes the server. This command will gracefully shut down the server, closing all connections and resources.
* _open_ - Opens the server. This command allows you to start the server if it was previously closed.
* _help_ - Displays the list of available commands. Use this command to get a quick overview of all the commands supported by the server console.
* _mods_ - Displays the list of mods. SVR.JS supports modularity. This command will show you the currently installed mods.
* _stop_ - Stops the server process. This command will terminate the SVR.JS server entirely.
* _clear_ - Clears the current page of the terminal. This command helps to clean up the terminal interface.
* _block <blocked>_ - Adds an IP address or a domain to the server's block list. Blocked clients will be denied access to the server.
* _unblock <blocked>_ - Removes an IP address or a domain from the server's block list. Unblocked clients can access the server normally.
* _restart_ - Restarts SVR.JS workers. This command will restart the server's worker processes, allowing for a fresh start of worker instances. (SVR.JS 3.0.0 or newer)
These commands provide an easy and convenient way to manage and control the SVR.JS server directly from the console.
### Updating SVR.JS
#### Using SVR.JS updater (included in SVR.JS installer package; GNU/Linux only)
If you installed SVR.JS using installer packages in April 5, 2024 and later, you can just run `sudo svrjs-updater` command to update SVR.JS to latest version. Once the update is done, restart your server OS or type `systemctl start svrjs` or `/etc/init.d/svrjs start` to restart SVR.JS.
For older installer packages, SVR.JS can be updated using SVR.JS updater by changing working directory to one containing SVR.JS updater, and running `sudo bash updater.sh` (**make sure _svrjs.zip_ file contains new version of SVR.JS**). Once the update is done, restart your server OS or type `systemctl start svrjs` or `/etc/init.d/svrjs start` to restart SVR.JS.
2024-03-15 21:53:12 +01:00
#### Using _create-svrjs-server_ tool
SVR.JS can be updated using _create-svrjs-server_ tool by changing working directory to one containing SVR.JS, and running one of those commands:
* `create-svrjs-server lts` - Latest SVR.JS LTS version
* `create-svrjs-server latest` - Latest SVR.JS version
* `create-svrjs-server 3.6.1` - SVR.JS 3.6.1 (replace 3.6.1 with your desired version)
Then you can run `node svr.js` or `bun run svr.js` to extract new version of SVR.JS and new Node.JS modules.
#### Manual updating
SVR.JS can be updated manually by extracting _svr.js_, _modules.compressed_ and _svr.compressed_ files from archive containing new version of SVR.JS to directory, to which older version of SVR.JS is installed (if you installed SVR.JS using SVR.JS installer, it is _/usr/lib/svrjs_). Then you can run `node svr.js` or `bun run svr.js` to extract new version of SVR.JS and new Node.JS modules.
### Common problems
* **Problem: _Access denied._ or _Permission denied. You may not have sufficient privileges to access the requested address._**
Solution: Run SVR.JS with elevated privileges. Check _config.json_. If you have installed SVR.JS with SVR.JS installer, grant Node.JS permissions using `setcap 'cap_net_bind_service=+ep' /usr/bin/node`.
* **Problem: _Address in use by another process._ or _Address is already in use by another process._**
Solution: Try to stop process using the same port as SVR.JS, and restart SVR.JS. Check _config.json_
* **Problem: _JSON Parse error._**
Solution: Check _config.json_ and correct JSON syntax errors. If it fails, delete _config.json_. SVR.JS will then create new _config.json_
* **Problem: _SVR.JS worker just crashed!!!_**
Solution: Check your SVR.JS configuration, mods and server-side JavaScript. If crash is related to SVR.JS itself, you can report it at _bugreports[at]svrjs[dot]org_, or ask on [SVR.JS bug reports board](https://forum.svrjs.org/svr-js-bug-reports).
* **Problem: _There was a problem while loading a "<mod name>" mod._**
Solution: Try deleting _temp_ directory. If it still won't work, report the problem to mod developer, or ask on [SVR.JS mod problems board](https://forum.svrjs.org/svr-js-mod-problems).
* **Problem: _There was a problem while loading server side JavaScript._**
Solution: Try deleting _temp_ directory. If it still won't work, check your _serverSideScript.js_ file, or ask on [Problems with server-side JavaScript board](https://forum.svrjs.org/problems-with-server-side-javascript).
* **Problem: _There was a problem while saving logs! Logs will not be kept in log file._**
Solution: Check your _log_ directory.
### Bun support
SVR.JS is currently partially compatible with Bun JavaScript runtime. In the benchmark shown below, SVR.JS on Bun 1.1 has around 2.8 times more requests per second and over 5 times lower maximum latency than SVR.JS on Node.JS 18.19.1 LTS.
![SVR.JS on Bun is faster than SVR.JS on Node.JS](/img/nodejs-vs-bun.png)
However, SVR.JS on Bun currently has these limitations:
* Proxy requests with _CONNECT_ method are not supported.
* WebSocket requests are not supported (via _req.socket_ API).
* There is just one worker process (Bun 1.0 and later; due to _cluster_ module not being implemented in Bun; SVR.JS shims the cluster module, but ports aren't shared in Bun 1.0 and later).
* PBKDF2 function blocks the event loop, which may cause denial of service.
* HTTP/2 is not supported (because Bun didn't implement HTTP/2 server in _http2_ module yet)
2024-03-15 21:53:12 +01:00
## Configuration
SVR.JS can be configured by modifying _config.json_ file.
### _config.json_ properties
The _config.json_ file contains various properties that you can customize to configure SVR.JS according to your specific requirements. Below are the available properties:
#### General Configuration
* _users_ (Array of Objects, SVR.JS 3.0.0 or newer)
* Users list for HTTP authentication. Use _svrpasswd_ tool to add, modify or delete users.
* _name_: User name for HTTP authentication (String)
* _pass_: Salted hash of the password (default SHA256 with appended salt, String)
* _salt_: Salt used to generate the SHA256 hash (String)
* _pbkdf2_: Flag used to determine, if hash is PBKDF2 (Boolean, SVR.JS 3.7.0 or newer)
* _scrypt_: Flag used to determine, if hash is scrypt (Boolean, SVR.JS 3.7.0 or newer)
* _port_ (Number or String, required)
* HTTP port for SVR.JS to listen on. For SVR.JS 3.6.0 and later, it can also be a Unix socket or Windows named pipe. For SVR.JS 3.9.0 and later, this can also be an IP address along with a port like _"192.168.0.2:80"_ or like _"\[fdad:8948:1053::2\]:80"_
* _pubport_ (Number, required)
* Public HTTP port for SVR.JS to display. It is also used in HTTP to HTTPS redirect.
* _sport_ (Number or String)
* HTTPS port for SVR.JS to listen on. For SVR.JS 3.6.0 and later, it can also be a Unix socket or Windows named pipe. For SVR.JS 3.9.0 and later, this can also be an IP address along with a port like _"192.168.0.2:80"_ or like _"\[fdad:8948:1053::2\]:80"_
* _spubport_ (Number)
* Public HTTPS port for SVR.JS to display. It is also used in HTTP to HTTPS redirect.
#### SSL Configuration
* _secure_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to enable HTTPS.
* _cert_ (String, required for HTTPS)
* Path to the SSL certificate file. Path is relative to SVR.JS installation directory, unless absolute path is specified.
* _key_ (String, required for HTTPS)
* Path to the RSA/ECDSA private key file. Path is relative to SVR.JS installation directory, unless absolute path is specified.
* _sni_ (Object, SVR.JS 3.0.0 or newer)
* SNI certificate paths for multiple domain names.
* _{domain\_name}_: Object with properties _cert_ and _key_ (path to SSL certificate and private key).
* _enableOCSPStapling_ (Boolean, SVR.JS 3.4.9 or newer)
* Option to enable OCSP stapling.
* _useClientCertificate_ (Boolean, SVR.JS 3.14.0 or newer)
* Option to require client to provide its certificate.
* _rejectUnauthorizedClientCertificates_ (Boolean, SVR.JS 3.14.0 or newer)
* Option to disable verification of client certificates.
* _cipherSuite_ (String, SVR.JS 3.14.0 or newer)
* Specification of cipher suites, replacing the default. For more information, see [Node.JS documentation](https://nodejs.org/docs/latest/api/tls.html#modifying-the-default-tls-cipher-suite).
* _ecdhCurve_ (String, SVR.JS 3.14.0 or newer)
* Specification of ECDH curves, for example `P-521:P-384:P-256`. Set the parameter to `auto` to select the curve automatically. You can use `openssl ecparam -list_curves` command to obtain available ECDH curves.
* _signatureAlgorithms_ (String, SVR.JS 3.14.0 or newer)
* Colon-seperated list for signature algorithms supported by the server. The list may contain digest algorithms (e.g. `SHA256`, `MD5`), public key algorithms (e.g. `RSA-PSS`, `ECDSA`), combinations of both (e.g. `RSA+SHA384`) or TLS v1.3 scheme names (e.g. `rsa_pss_pss_sha512`). For more information, see [OpenSSL man pages](https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set1_sigalgs_list.html).
* _tlsMinVersion_ (String, SVR.JS 3.14.0 or newer)
* Minimum TLS version, it can be `TLSv1.3`, `TLSv1.2`, `TLSv1.1`, or `TLSv1`. It is not recommended to set it less than TLSv1.2, unless it's required for interoperability. This is because of security vulnerabilities of TLS v1.1 and TLS v1.
* _tlsMaxVersion_ (String, SVR.JS 3.14.0 or newer)
* Maximum TLS version, it can be `TLSv1.3`, `TLSv1.2`, `TLSv1.1`, or `TLSv1`.
#### Domain and Redirect Configuration
* _domain_ (String)
* Domain for SVR.JS to display. (In SVR.JS 2.x, it was _domian_)
* _wwwredirect_ (Boolean)
* Option to enable redirects to domain name that begins with "www.". You need to first set _domain_ property in order for this option to have effect. This property didn't work in SVR.JS versions from 3.3.0 to 3.14.4
#### Error Pages and Logging Configuration
* _page404_ (String)
* Path to a custom 404 error page (after pages defined in _errorPages_ property).
* _errorPages_ (Array; SVR.JS 3.8.0 or newer)
* Custom error pages configuration.
* _scode_: HTTP status code specification for error page (Number, SVR.JS 3.8.0 or newer).
* _path_: Path for error page (String, SVR.JS 3.8.0 or newer).
* _host_: Applicable host name for this error page (optional; String, SVR.JS 3.8.0 or newer).
* _ip_: Applicable IP address for this error page. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer).
* _serverAdministratorEmail_ (String, SVR.JS 3.0.0 or newer)
* Server administrator e-mail address to be displayed in default 5xx error pages.
* _enableLogging_ (Boolean)
* Option to enable saving logs to a log file.
#### HTTP Configuration
* _enableCompression_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to enable HTTP compression.
* _enableHTTP2_ (Boolean)
* Option to enable HTTP/2.
* _enableDirectoryListing_ (Boolean)
* Option to enable directory listing. If disabled, it returns a 403 error page.
* _enableDirectoryListingWithDefaultHead_ (Boolean)
* Option to enable default header and footer on directory listing.
* _nonStandardCodes_ (Array of Objects)
* Non-standard status codes configuration:
* _scode_: Non-standard status code to apply. (Number)
* _url_: URL to which this status code applies (after URL rewriting; String).
* _regex_: Regex string (e.g. `"/^\\/index\\.php(?:$|[\\/?#])/"`) for matching the source URL (after URL rewriting) this status code applies to (with or without the query string). (Regex String, SVR.JS 3.0.0 or newer)
* _location_: URL to which it is redirected on 301 and 302 status codes. (String)
* _realm_: HTTP authentication realm on 401 status code. (String, SVR.JS 3.0.0 or newer)
* _disableBruteProtection_: Option to disable brute force protection on 401 status code. (Boolean, SVR.JS 3.4.8 or newer)
* _host_: Applicable host name for this status code. (optional; String, SVR.JS 3.8.0 or newer)
* _ip_: Applicable IP address for this status code. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer)
* _userList_: Allowed users for HTTP authentication. (optional; Array of Strings, SVR.JS 3.8.0 or newer)
* _dontCompress_ (Array of Regex Strings, SVR.JS 3.0.0 or newer)
* URLs for which HTTP compression will be disabled.
* _enableIPSpoofing_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to enable identifiying client's originating IP address through the _X-Forwarded-For_ header (**for use in websites hidden behind a reverse proxy**, not recommeded if you're not using SVR.JS behind a reverse proxy, since hackers can spoof client IP address via this header).
* _enableETag_ (Boolean, SVR.JS 3.6.1 or newer)
* Option to enable ETags.
* _customHeaders_ (Object, SVR.JS 3.0.0 or newer)
* Custom HTTP headers (configured as a JavaScript object) with a _{path}_ template representing the request path (after URL rewriting).
* _http2Settings_ (Object, SVR.JS 3.14.0 or newer)
* HTTP/2 protocol settings object. See [Node.JS documentation](https://nodejs.org/docs/latest/api/http2.html#settings-object) for more information.
* _headerTableSize_: Maximum number of bytes used for header compression. Minimum value is 0. Maximum value is 2<sup>32</sup>-1. Default is 4096 (Number, SVR.JS 3.14.0 or newer).
* _enablePush_: Option to enable HTTP/2 Push Streams. It is enabled by default (Boolean, SVR.JS 3.14.0 or newer).
* _initialWindowSize_: Sender's initial window size in bytes for stream-level flow control. Minimum value is 0. Maximum value is 2<sup>32</sup>-1. Default is 65535 (Number, SVR.JS 3.14.0 or newer).
* _maxFrameSize_: Largest frame payload size in bytes. Minimum value is 16384. Maximum value is 2<sup>24</sup>-1. Default is 16384 (Number, SVR.JS 3.14.0 or newer).
* _maxConcurrentStreams_: Maximum number of concurrent streams allowed on HTTP/2 session. Minimum value is 0. Maximum value is 2<sup>32</sup>-1. Default is 2<sup>32</sup>-1 (Number, SVR.JS 3.14.0 or newer).
* _maxHeaderListSize_: Maximum size (uncompressed octets) of acceptable header list. Minimum value is 0. Maximum value is 2<sup>32</sup>-1. Default is 65535 (Number, SVR.JS 3.14.0 or newer).
* _maxHeaderSize_: Alias for _maxHeaderListSize_ (Number, SVR.JS 3.14.0 or newer).
* _enableConnectProtocol_: Option to enable the "Extended Connect Protocol" defined by RFC 8441 (Number, SVR.JS 3.14.0 or newer).
* _customSettings_: Additional settings not implemented yet in Node.JS and its underlying libraries. Object key defines the numeric value of the settings type (as defined in the "HTTP/2 SETTINGS" registry established by RFC 7540). Object values define actual numeric value of the settings. Settings types should be greater than 6 and less than 2<sup>16</sup>-1. Values should be in range from 0 to 2<sup>32</sup>-1. Currently you can specify up to 10 custom settings (Object, SVR.JS 3.14.0 or newer).
#### Security Configuration
* _blacklist_ (Array of Strings)
* Block list of IP addresses and CIDR ranges.
* _disableServerSideScriptExpose_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to disable exposing SVR.JS script, server-side JavaScript, SVR.JS mods, and Node.JS modules. **It's strongly recommended to set this property to _true_ if you're using SVR.JS server-side JavaScript.** If you want to additionally prevent fingerprinting SVR.JS by accessing _/serverSideScript.js_, you can add URL rewrite rule, that defines rewriting of _/serverSideScript.js_ to a non-existent page.
* _enableRemoteLogBrowsing_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to enable browsing server logs from an HTTP client. Applicable only when you're not using custom web root. **It's not recommended to enable this, because it provides valuable information for attackerss, unless you're protecting _log_ folder with HTTP authentication.**
* _exposeServerVersion_ (Boolean)
* Option to expose the server version via _Server_ header. If it is disabled, the header will have "SVR.JS" value.
* _rewriteDirtyURLs_ (Boolean, SVR.JS 3.7.0 or newer)
* Option to rewrite "dirty" URLs (those filtered by path sanitizer) instead of redirecting them.
* _exposeModsInErrorPages_ (Boolean, SVR.JS 3.4.29, 3.9.1 or newer)
* Option to expose SVR.JS mod information through default error pages (for example in _SVR.JS RedBrick/2.4.2 on forum.svrjs.org_ signature). Mod information is never exposed through _Server_ header (just SVR.JS information).
#### Virtual Host Configuration
* _enableDirectoryListingVHost_ (Array of Objects; SVR.JS 3.8.0 or newer)
* Array containing options to enable directory listings for specific virtual hosts.
* _host_: Applicable host name for this rule (String, SVR.JS 3.8.0 or newer).
* _ip_: Applicable IP address for this rule. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer).
* _enabled_: Has the same effect as _enableDirectoryListing_ (Boolean, SVR.JS 3.8.0 or newer).
* _customHeadersVHost_ (Array of Objects; SVR.JS 3.8.0 or newer)
* Array containing custom headers for specific virtual hosts.
* _host_: Applicable host name for this rule (String, SVR.JS 3.8.0 or newer).
* _ip_: Applicable IP address for this rule. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer).
* _headers_: Has the same effect as _customHeaders_ property (Object, SVR.JS 3.8.0 or newer).
* _wwwrootPostfixesVHost_ (Array of Objects; SVR.JS 3.14.0 or newer)
* Array containing web root postfixes assigned for each virtual host. For example: the source URL is _/page.html_ and postfix is _svrjs_; the rewritten URL is _/svrjs/page.html_. URL rewriting (with rules defined in the _rewriteMap_ property) will be processed after assigning web root postfixes.
* _host_: Applicable host name for this prefix (String, SVR.JS 3.14.0 or newer).
* _ip_: Applicable IP address for this prefix. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer).
* _postfix_: Postfix inserted before the request URL (String, SVR.JS 3.14.0 or newer).
* _skipRegex_: Regex string (e.g. `"/^\\/index\\.php(?:$|[\\/?#])/"`) for matching request URLs to skip (optional; Regex String, SVR.JS 3.14.0 or newer).
* _wwwrootPostfixPrefixesVHost_ (Array of Strings; SVR.JS 3.14.0 or newer)
* Array containing URL strings to insert before web root postfix (for all hosts). For example: the source URL is _/cgi-bin/gitweb.cgi_, postfix is _svrjs_ and the postfix prefix is _/cgi-bin_; the rewritten URL is _/cgi-bin/svrjs/gitweb.cgi_.
* _allowPostfixDoubleSlashes_ (Boolean, SVR.JS 3.14.4 or newer)
* Option to allow double slashes, when inserting web root postfixes. If set to `false`, double slashes are removed by postfix insertion function. It may create issues with double slash URLs not having prefixes.
#### Miscellaneous Configuration
* _rewriteMap_ (Array of Objects, SVR.JS 3.0.0 or newer)
* Map for URL rewriting engine. Entries of the array are URL rewrite rules.
* _definingRegex_: Regex string (e.g. `"/^\\/index\\.php(?:$|[\\/?#])/"`) for matching the source URL it applies to (Regex String, SVR.JS 3.0.0 or newer).
* _host_: Applicable host name for this URL rewriting rule (optional; String, SVR.JS 3.8.0 or newer).
* _ip_: Applicable IP address for this URL rewriting rule. Use this property to specify destination server IP address instead of _host_ property to prevent _Host_ header attacks. (optional; String, SVR.JS 3.14.1 or newer).
* _append_: String to append after the end of URL (optional; String, SVR.JS 3.0.0 or newer).
* _isNotDirectory_: Option to disable rewrite rule, when directory defined by the path exists (optional; Boolean, SVR.JS 3.13.0 or newer).
* _isNotFile_: Option to disable rewrite rule, when file defined by the path exists (optional; Boolean, SVR.JS 3.13.0 or newer).
* _allowDoubleSlashes_: Option to allow double slashes in the URL. If set to `false`, then URL rewriter removes double slashes. You may use `\\/{1,2}` instead of `\\/` in URL rewriting regular expressions (optional; Boolean, SVR.JS 3.14.4 or newer).
* _replacements_: Regex string (e.g. `"/^\\/index\\.php(?:$|[\\/?#])/"`) replacements (Array of Objects, SVR.JS 3.0.0 or newer).
* _regex_: Regex string (e.g. `"/^\\/index\\.php(?:$|[\\/?#])/"`) for matching the source URL this replacement applies to (Regex String, SVR.JS 3.0.0 or newer).
* _replacement_: Replacement string (you can use for example "_$1_" for first capturing group; String, SVR.JS 3.0.0 or newer).
* _disableNonEncryptedServer_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to disable the HTTP server if the HTTPS server is running.
* _disableToHTTPSRedirect_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to disable redirects from the HTTP server to the HTTPS server.
* _allowStatus_ (Boolean, SVR.JS 3.0.0 or newer)
* Option to enable _/svrjsstatus.svr_ page for monitoring server status (by default it's enabled).
* _wwwroot_ (String, SVR.JS 3.0.0 or newer)
* Path to the root directory from which SVR.JS serves files and loads its server-side JavaScript. Defaults to the directory on which SVR.JS resides.
* _disableUnusedWorkerTermination_ (Boolean, SVR.JS 3.7.0 or newer)
* Option to disable termination of unused SVR.JS workers.
* _useWebRootServerSideScript_ (Boolean, SVR.JS 3.9.0 or newer)
* Option to use server-side JavaScript in web root. If it is set to _false_, the server-side JavaScript is loaded from SVR.JS installation directory.
* _disableTrailingSlashRedirects_ (Boolean, SVR.JS 3.12.0 or newer)
2024-04-02 18:16:01 +02:00
* Option to disable redirects from URLs referencing to directories (but without a trailing slash) to URL with a trailing slash. For forwards proxy applications and SVR.JS 3.14.9 and earlier, it needs to be _true_, or else the server will just do redirect loops.
2024-03-15 21:53:12 +01:00
* _environmentVariables_ (Object, SVR.JS 3.12.0 or newer)
* Envrionment variables. These can be used for CGI web applications and server-side JavaScript.
* _allowDoubleSlashes_ (Boolean, SVR.JS 3.14.4 or newer)
* Option to allow double slashes in the URL. If set to `false`, double slashes are removed by URL sanitizer. Double slashes at the beginning of path (e.g. in _//config.json_) are always removed. Doesn't affect URL rewriting, in that case please configure the _allowDoubleSlashes_ property in the URL rewriting rule. It may allow some configuration file leaks, if web root is in the SVR.JS installation directory.
2024-08-07 06:31:36 +02:00
* _optOutOfStatisticsServer_ (Boolean, SVR.JS 3.15.6 or newer)
* Option to opt out of sending data to the statistics server. You can use this option to increase the privacy of SVR.JS.
2024-03-15 21:53:12 +01:00
#### Deprecated and Removed Properties
The following properties are deprecated or removed in newer versions of SVR.JS, and modifying them might not have any effect on the server:
* _timestamp_ (Number, **DON'T CHANGE**)
* Timestamp of server starting. (This property should not be modified.)
* _version_ (String, removed in SVR.JS 3.4.0, **DON'T CHANGE**)
* SVR.JS version (This property is no longer used and should not be modified.)
#### Example Configuration
Here's an example _config.json_ file illustrating some of the available properties:
```json
{
"port": 8080,
"pubport": 80,
"sport": 8443,
"spubport": 443,
"domain": "example.com",
"wwwroot": "/var/www/html",
"wwwredirect": true,
"page404": "custom_404.html",
"enableLogging": true,
"enableDirectoryListing": true,
"enableCompression": true,
"enableHTTP2": true,
"enableETag": true,
"secure": true,
"cert": "path/to/certificate.crt",
"key": "path/to/private.key",
"exposeServerVersion": false,
"exposeModsInErrorPages": false,
"disableServerSideScriptExpose": true,
"enableIPSpoofing": true,
"allowStatus": false,
"useWebRootServerSideScript": false,
"rewriteMap": [
{
"definingRegex": "/^\\/serverSideScript\\.js(?:$|[#?])/",
"replacements": [
{
"regex": "/^\\/serverSideScript\\.js($|[#?])/",
"replacement": "/NONEXISTENT_PAGE$1"
}
]
},
{
"definingRegex": "/^\\/old-url$/",
"replacements": [
{
"regex": "/^\\/old-url$/",
"replacement": "/new-url"
}
]
}
],
"customHeaders": {
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff"
}
}
```
### CLI options
* _-h_, _-?_, _/h_, _/?_ or _--help_ - displays help
* _--clean_ - cleans up files created by SVR.JS
* _--reset_ - resets SVR.JS to default settings (**WARNING: DANGEROUS**)
* _--secure_ - runs HTTPS server
* _--disable-mods_ - disables mods (safe mode)
* _--single-threaded_ - runs single-threaded
* _-v_ or _--version_ - displays server version
### Page customization
You can easily customize the appearance of pages served by SVR.JS by adding custom head and foot sections. These sections can be linked to every _.html_ file served by SVR.JS.
To customize the head, create a _head.html_ or _.head_ (SVR.JS 3.0.0 or newer) file in the web root directory. For the foot, create a _foot.html_ or _.foot_ (SVR.JS 3.0.0 or newer) file in the web root directory. Both custom head and foot sections will also be linked to directory listings if the _enableDirectoryListingWithDefaultHead_ property in _config.json_ is set to _true_.
For individual directory listings, you can add custom head and foot sections as well. Create a _HEAD.html_ or _.dirhead_ (SVR.JS 3.0.0 or newer) file for the head section, and a _FOOT.html_ or _.dirfoot_ (SVR.JS 3.0.0 or newer) file for the foot section in the specific directory you want to customize. You can also add a description of the directory (in HTML format) by creating a _.maindesc_ file in the respective directory. You can even apply CSS styles to directory listing table (using `#directoryListing` CSS selector and custom directory listing head and foot).
You can add index page to web root or directories in web root with one of those file names: _index.html_, _index.htm_ and _index.xhtml_.
From SVR.JS 3.5.0, you can change directory listing icons by replacing the icons in the _.dirimages_ directory located in the web root. If an icon is not present in the _.dirimages_ directory in the web root, SVR.JS will fall back to using icons in the _.dirimages_ directory in the same directory as the SVR.JS script.
### Custom error pages
You can configure SVR.JS to serve custom error pages by adding _.&lt;errorcode&gt;_ (SVR.JS 3.0.0 or newer) or _&lt;errorcode&gt;.html_ pages. For the 404 error, you can specify it by changing the _page404_ property in _config.json_. From SVR.JS 3.8.0 onwards, you can use _errorPages_ property in _config.json_ to specify path to each custom error page.
When designing custom error pages, you can make use of the following placeholders or templates:
* _{errorMessage}_ - Displays the error code along with its short description.
* _{errorDesc}_ - Displays a longer description of the server error.
* _{stack}_ - Displays the error stack, which is equivalent to the _Error.stack_ property in JavaScript.
* _{path}_ - Shows the path of the page that caused the error.
* _{server}_ - Displays the server version string along with the hostname. For example, "_SVR.JS/3.9.6 (Linux; Node.JS/v12.22.12) on 127.0.0.1:8080_" or simply "_SVR.JS on svrjs.org_".
* _{contact}_ - Displays the contact information of the server administrator, which can be set using the _serverAdministratorEmail_ property in _config.json_.
### User management
You can manage users for HTTP authentication in SVR.JS by using _svrpasswd.js_ tool (SVR.JS 3.0.0 or newer). Usage is `node svrpasswd.js [-h] [--help] [-?] [/h] [/?] [-x] [-a|--add|-d|--delete] <username>`. Command-line options:
* _-h_, _-?_, _/h_, _/?_ or _--help_ - displays help
* _-a_ or _--add_ - adds an user
* _-d_ or _--delete_ - deletes an user
* _-x_ - forces password hashing algorithm change
In SVR.JS 3.7.0 and newer, you can choose between 3 password hashing algorithms:
* **Salted SHA256** (1 iteration) - fastest and uses least memory, but less secure
* **PBKDF2** (PBKDF2-HMAC-SHA512, 36250 iterations) - more secure and uses less memory, but slower
* **scrypt** (N=2<sup>14</sup>, r=8, p=1) - faster and more secure, but uses more memory
### HTTP authentication
You can add HTTP basic authentication by including a 401 code (with _scode_ property set to 401) entry in the _nonStandardCodes_ property of _config.json_. To enable HTTP basic authentication, you need to specify the URL you want to restrict in the _url_ or _regex_ property of the entry. Additionally, you can set the authentication realm in the _realm_ property. If the realm is not specified, the default realm is "_SVR.JS HTTP Basic Authorization_". The encoding used for authentication will always be UTF-8.
By default, SVR.JS enables brute force protection for HTTP authentication, so you don't need to worry about potential brute force attacks against the authentication mechanism.
From SVR.JS 3.8.0 onwards, you can specify a list of allowed users in the _userList_ property.
### Redirects
Setting up HTTP redirects is simple with SVR.JS. You can add a 301 or 302 code (with _scode_ property set to 301 or 302) entry to the _nonStandardCodes_ property in _config.json_. The entry should specify the source URL for the redirect in the _url_ or regular expression string for the redirect in _regex_ property (for example `"/\\/blog($|[#?\\/].*)/"`), and the destination URL in the _location_ property (for regular expressions, you can use for example "_$1_" for contents of first capturing group). Destination location can be relative to current site (for example _/blogs_) or a full URL (for example _https://blog.example.com_).
Please be cautious when setting up redirects to avoid redirect loops, as they can cause unintended behavior and potentially impact the performance of your server.
From SVR.JS 3.8.0 onwards, you can specify a hostname for which this redirect applies in _host_ property. If you want to move your website to new address, you can add redirect to new website and specify _host_ property to be host name of the old website (for example _oldsite.example_), _location_ property to be a location of new website with "_$1_" appended (for example "_https://newsite.example$1_") and _regex_ property to be `"/(.*)/"` (regular expression, which matches everything to capturing group).
### URL rewriting
You can set up URL rewriting by adding entries to _rewriteMap_ property in _config.json_ file. See ["_config.json_ properties" section](#config-json-properties) for URL rewrite rules syntax.
### Log viewing
To make log viewing easier, SVR.JS 3.x and later included it's log viewer utility under _logviewer.js_. SVR.JS log viewer is interactive.
You can also manually view logs, and highlight them using SVR.JS log highlighter utility under _loghighlight.js_ (SVR.JS 3.0.0 or newer). Usage: `&lt;some process&gt; | node loghighlight.js [-h] [--help] [-?] [/h] [/?]`.
SVR.JS stores it's logs in _log_ directory. Server logs look like this:
<pre>
[2023-07-04T18:50:54.610Z] SERVER MESSAGE [Request Id: c0ffd0]: Somebody connected to port 80...
[2023-07-04T18:50:54.611Z] <span style="color: #5050ff">SERVER REQUEST MESSAGE [Request Id: c0ffd0]: Client ::ffff:127.0.0.1:33670 wants content in localhost/leak.svr</span>
[2023-07-04T18:50:54.611Z] <span style="color: #5050ff">SERVER REQUEST MESSAGE [Request Id: c0ffd0]: Client uses Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: There was an error while processing the request!</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: Stack:</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: RangeError [ERR_INVALID_OPT_VALUE]: The value "4294967296" is invalid for option "size"</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at Function.allocUnsafe (buffer.js:290:3)</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at /home/ubuntu/svr.js.3.3.3/temp/serverSideScript.js:70:18</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at /home/ubuntu/svr.js.3.3.3/temp/modloader/primitiveanalytics.tar.gz/index.js:28:23</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at modExecute (/home/ubuntu/svr.js.3.3.3/svr.js:2981:9)</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at Server.reqhandler (/home/ubuntu/svr.js.3.3.3/svr.js:3741:11)</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at Server.emit (events.js:198:13)</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at parserOnIncoming (_http_server.js:691:12)</span>
[2023-07-04T18:50:54.625Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: at HTTPParser.parserOnHeadersComplete (_http_common.js:111:17)</span>
[2023-07-04T18:50:54.626Z] <span style="color: #ff5050">SERVER RESPONSE ERROR MESSAGE [Request Id: c0ffd0]: Server responded with 500 code.</span>
[2023-07-04T18:50:54.630Z] SERVER MESSAGE [Request Id: c0ffd0]: Client disconnected.
[2023-07-04T18:50:54.699Z] SERVER MESSAGE [Request Id: 1be453]: Somebody connected to port 80...
[2023-07-04T18:50:54.699Z] <span style="color: #5050ff">SERVER REQUEST MESSAGE [Request Id: 1be453]: Client ::ffff:127.0.0.1:33670 wants content in localhost/favicon.ico</span>
[2023-07-04T18:50:54.700Z] <span style="color: #5050ff">SERVER REQUEST MESSAGE [Request Id: 1be453]: Client uses Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0</span>
[2023-07-04T18:50:54.709Z] SERVER MESSAGE [Request Id: 1be453]: Client disconnected.
[2023-07-04T18:50:54.710Z] <span style="color: #00ff00">SERVER RESPONSE MESSAGE [Request Id: 1be453]: Server responded with 200 code.</span>
[2023-07-04T18:50:54.712Z] <span style="color: #00ff00">SERVER RESPONSE MESSAGE [Request Id: 1be453]: Client successfully recieved content.</span>
</pre>
First on the line is timestamp. Second is message type, optionally with request ID. Last is message contents.
### Environment variables
#### SVR.JS 3.12.0 and newer
You can configure environment variables by configuring _environmentVariables_ property in _config.json_.
#### Older SVR.JS versions
SVR.JS seamlessly passes through externally set environment variables to mods and server-side JavaScript, allowing you to customize and control your application's behavior based on these variables.
If you have a start-up script or use the command line to run SVR.JS, you can easily set environment variables before launching the server. Here's an example of how you can do it in a bash script:
```bash
export NODE_ENV=production
export OPENAI_API_KEY=redacted
node svr.js
```
In this example, we're setting two environment variables, `NODE_ENV` and `OPENAI_API_KEY`, before running the `node svr.js` command. These environment variables will be accessible within your mods and server-side JavaScript, allowing you to utilize them to configure and adapt your application as needed.
If you have installed SVR.JS using SVR.JS installer then you may modify _/etc/init.d/svrjs_ script (_do_start_ method) like this:
```bash
do_start()
{
if [ ! -f "$lockfile" ] ; then
echo -n $"Starting $servicename: "
runuser -l "$user" -c "export GIT_HTTP_EXPORT_ALL=1; export GIT_PROJECT_ROOT=/var/lib/git; $nodejs $server > /dev/null &" && echo_success || echo_failure
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch "$lockfile"
else
echo "$servicename is locked."
RETVAL=1
fi
}
```
If you have used SVR.JS installer on GNU/Linux distribution that uses _systemd_, then you may add _Environment_ directives in _Service_ section in _systemd_ service file (_/etc/systemd/system/svrjs.service_) like this:
```ini
[Unit]
Description=SVR.JS web server
After=network.target
[Service]
Type=simple
User=svrjs
ExecStart=/usr/bin/env node /usr/lib/svrjs/svr.js
Environment=GIT_HTTP_EXPORT_ALL=1
Environment=GIT_PROJECT_ROOT=/var/lib/git
Restart=on-failure
[Install]
WantedBy=multi-user.target
```
Using environment variables can be a powerful way to manage different configurations for development, staging, and production environments, configure your CGI web applications, or to securely store sensitive information like API keys and passwords.
Remember that when you set environment variables externally, they will be available to all instances of SVR.JS running on your system. Exercise caution when using sensitive information as environment variables, and ensure that they are properly secured and protected.
By leveraging environment variables, you can enhance the flexibility and security of your SVR.JS application and streamline your deployment process.
### CGI/SCGI/JSGI/PHP
In order to use CGI with SVR.JS, you need to install RedBrick mod. For SCGI you need to install OrangeCircle, while for JSGI you need to install YellowSquare mod. [Download these mods.](https://svrjs.org/mods)
#### CGI and PHP via RedBrick
RedBrick supports running CGI programs and PHP files (RedBrick 2.3.0 and newer) in cgi-bin directory. RedBrick 2.5.0 and newer support running CGI programs and PHP files outside cgi-bin directory. You can configure file extensions outside of cgi-bin directory handled by RedBrick in _redbrick-scriptexts.json_ file in SVR.JS installation directory like this:
```json
[
".php",
".cgi"
]
```
RedBrick custom interpreters (from RedBrick 2.3.2; in earlier versions it is broken) can be configured in _redbrick-interpreters.json_ file in SVR.JS install directory like this:
```json
{
".pl": ["perl"],
".py": ["python"],
".sh": ["bash"],
".pyw": ["python"],
".rb": ["ruby"],
".php": ["php-cgi"]
}
```
RedBrick 2.3.0 and newer support PHP-CGI, while RedBrick 2.3.1 and newer support URL rewriting. RedBrick 2.3.6 and newer work with Windows (older ones always threw an 500 error while trying to execute CGI scripts on Windows). RedBrick 2.4.3 and newer work with web root outside SVR.JS installation directory (older ones need _config.json_ file in web root with valid JSON data; not necessarily related to _config.json_ in SVR.JS installation directory)
RedBrick 2.4.1 and newer allows to disable some default interpreter configuration using "null" like this:
```json
{
".pl": null,
".py": null,
".rb": null,
".exe": null
}
```
As of RedBrick 2.4.3, there are default interpreter configurations for _.pl_, _.py_, _.sh_, _.ksh_, _.csh_, _.rb_ and _.php_ files. If server is running on Windows, then there will be additional default interpreter configuration for _.exe_, _.bat_, <s>_.cmd_</s> (dropped in RedBrick 2.5.0) and _.vbs_ files.
SVR.JS currently supports PHP-CGI through RedBrick mod. <s>PHP is currently supported only inside _cgi-bin_ directory in SVR.JS web root.</s> RedBrick 2.5.0 and newer supports PHP outside of _cgi-bin_ directory. You need to modify PHP configuration file (usually at _/etc/php/&lt;php version&gt;/cgi/php.ini_) and set _cgi.force_redirect_ property to _0_, otherwise PHP-CGI will not work and just display a warning about PHP-CGI binary being compiled with force-cgi-redirect enabled. **It's recommended to use directories outside of _cgi-bin_ for user uploads and downloads** (so that RedBrick will not treat uploaded scripts with shebang and ELF binary files as CGI applications and try to execute them, potentially resulting in hacker-uploaded malware infections, remote code execution vulnerabilities or 500 Internal Server Errors).
For security reasons, you may disable directory listing for _cgi-bin_ (and also other directories) through _disableDirectoryListing_ or _disableDirectoryListingVHost_ options in SVR.JS configuration.
#### SCGI via OrangeCircle
OrangeCircle can be configured in _orangecircle-config.json_ file in SVR.JS install directory like this:
```json
{
"path": "/scgi",
"host": "localhost",
"port": 4000
}
```
OrangeCircle 1.0.7 and newer work with web root outside SVR.JS installation directory (older ones need _config.json_ file in web root with valid JSON data; not necessarily related to _config.json_ in SVR.JS installation directory)
#### JSGI via YellowSquare
YellowSquare supports running JSGI scripts only in jsgi-bin directory. YellowSquare runs JSGI scripts, that are either with _.jsgi_ or _.jsgi.js_ extension. Every change in JSGI application requires a restart of SVR.JS in order to be applied.
YellowSquare 1.0.3 and newer work with web root outside SVR.JS installation directory (older ones need _config.json_ file in web root with valid JSON data; not necessarily related to _config.json_ in SVR.JS installation directory)
For security reasons, you may disable directory listing for _jsgi-bin_ (and also other directories) through _disableDirectoryListing_ or _disableDirectoryListingVHost_ options in SVR.JS configuration.
### FastCGI/PHP-FPM
In order to use FastCGI with SVR.JS, you need to install GreenRhombus mod. [Download the mod.](https://svrjs.org/mods)
#### GreenRhombus notes
GreenRhombus' path and FastCGI server address can be configured in _greenrhombus-config.json_ file in the SVR.JS install directory.
Example configuration (with FastCGI server listening with port):
```json
{
"path": "/fastcgi",
"host": "localhost",
"port": 7000
}
```
Example configuration (with FastCGI server listening on socket):
```json
{
"path": "/fastcgi",
"socketPath": "/run/fastcgi.sock"
}
```
You can configure file extensions outside of path specified in _greenrhombus-config.json_ file handled by GreenRhombus in _greenrhombus-scriptexts.json_ file in SVR.JS installation directory like this:
```json
[
".php"
]
```
#### PHP-FPM
GreenRhombus supports running PHP files through PHP-FPM. If you want to use GreenRhombus only for PHP-FPM, configure _greenrhombus-config.json_ like this (in this case we're using socket in _/run/php/php8.2-fpm.sock_; you can check it in PHP-FPM configuration file, e.g. _/etc/php/8.2/fpm/pool.d/www__.conf_; configure it without _path_ property):
```json
{
"socketPath": "/run/php/php8.2-fpm.sock"
}
```
And configure _greenrhombus-scriptexts.json_ like this:
```json
[
".php"
]
```
PHP-FPM may run on different user than SVR.JS web server, so you may need to set permissions for the user, which PHP-FPM runs on.
If you are using PHP-FPM only for SVR.JS, you can set the _listen.owner_ and _listen.group_ properties to _svrjs_ in the PHP-FPM configuration file (e.g. _/etc/php/8.2/fpm/pool.d/www__.conf_).
2024-04-14 17:28:43 +02:00
### Forward proxy notes
In order to use SVR.JS as a forward proxy, you need to install forward-proxy-mod SVR.JS mod. [Download this mod.](https://svrjs.org/mods)
If you are using forward-proxy-mod, then local IP addresses and _localhost_ are also accessible from the proxy. You may block these using a firewall, if you don't want these to be accessible from the proxy
2024-03-15 21:53:12 +01:00
### Reverse proxy configuration
In order to use SVR.JS as a reverse proxy, you need to install reverse-proxy-mod SVR.JS mod. [Download this mod.](https://svrjs.org/mods)
Configuration file of reverse-proxy-mod is _reverse-proxy-config.json_ inside SVR.JS installation directory. Keys of configuration object are domain names (or paths from reverse-proxy-mod 1.1.1), for which it's settings apply. Values are object with those properties:
* _hostname_ - Hostname of origin server.
* _port_ - Port of origin server.
* _secureHostname_ - Hostname of origin server (access via HTTPS).
* _securePort_ - Port of origin server (access via HTTPS).
reverse-proxy-mod 1.1.0 and newer support HTTP upgrades (including WebSocket).
If you're using per-host URL rewrite rules and running multiple sites on one SVR.JS instance (instead of proxying them all to specific web servers; assuming that you're using SVR.JS 3.8.0 or newer; shared hosting), use paths referring to URL rewrite destinations instead of domain names. However if you're planning to use VPSes (virtualized servers) or run different web server instances and use SVR.JS with reverse-proxy-mod as a reverse proxy for them, use domain names instead.
If you're using SVR.JS just as a reverse proxy (for VPSes or other web server instances, and not serving websites from proxy itself), set _disableServerSideScriptExpose_ to _false_, set web root to outside SVR.JS installation directory, empty out _rewriteMap_, _nonStandardCodes_, _enableDirectoryListingVHost_, _customHeadersVHost_, _wwwrootPostfixesVHost_, _wwwrootPostfixPrefixesVHost_ to `[]`, empty out _customHeaders_ to `{}`, set _disableTrailingSlashRedirects_ to _true_, set _allowDoubleSlashes_ to _true_, and set _disableToHTTPSRedirect_ to _true_, in order to avoid interference involving SVR.JS web server (use this configuration when proxy itself doesn't use SVR.JS server-side JavaScript not including SVR.JS mods).
### Virtual hosts
When you're not planning to use SVR.JS server-side JavaScript or SVR.JS mods implementing individual web applications and plan to use SVR.JS similarly to Apache, nginx or IIS (static-only, PHP, CGI or JSGI), you can use virtual host-like functionality (name-based; IP-based from SVR.JS 3.14.1 and newer) with SVR.JS 3.8.0 or newer.
You can set up custom error pages, URL rewriting rules and non-standard status code settings per-host like this (assuming that you want to also include CGI support through RedBrick):
```json
{
"users": [],
"port": 80,
"pubport": 80,
"page404": "404.html",
"blacklist": [],
"nonStandardCodes": [
{
"url": "/anothersite.example/dl",
"location": "/download",
"host": "anothersite.example",
"scode": 301
},
{
"url": "/anothersite.example/downloads",
"location": "/download",
"host": "anothersite.example",
"scode": 301
}
],
"enableCompression": true,
"customHeaders": {},
"enableHTTP2": false,
"enableLogging": true,
"enableDirectoryListing": true,
"enableDirectoryListingWithDefaultHead": false,
"serverAdministratorEmail": "[no contact information]",
"stackHidden": false,
"enableRemoteLogBrowsing": false,
"exposeServerVersion": true,
"disableServerSideScriptExpose": true,
"rewriteMap": [
{
"definingRegex": "/^(?!\\/(?:\\.dirimages|cgi-bin)(?:$|[\\/#?]))/",
"host": "website.example",
"replacements": [
{
"regex": "/(.*)/",
"replacement": "/website.example$1"
}
]
},
{
"definingRegex": "/^\\/cgi-bin(?:$|[\\/#?])/",
"host": "website.example",
"replacements": [
{
"regex": "/^\\/cgi-bin($|[\\/#?].*)/",
"replacement": "/cgi-bin/website.example$1"
}
]
},
{
"definingRegex": "/^(?!\\/(?:\\.dirimages|cgi-bin)(?:$|[\\/#?])|\\/index(?:$|[\\/#?]))/",
"host": "anothersite.example",
"replacements": [
{
"regex": "/(.*)/",
"replacement": "/anothersite.example$1"
}
]
},
{
"definingRegex": "/^\\/index(?:$|[\\/#?])/",
"host": "anothersite.example".
"replacements": [
{
"regex": "/^\\/index/",
"replacement": "/anothersite.example/"
}
]
},
{
"definingRegex": "/^\\/cgi-bin(?:$|[\\/#?])/",
"host": "anothersite.example",
"replacements": [
{
"regex": "/^\\/cgi-bin($|[\\/#?].*)/",
"replacement": "/cgi-bin/anothersite.example$1"
}
]
},
{
"definingRegex": "/^\\/(?:cgi-bin\\/)?(?:website\\.example|anothersite\\.example)(?:$|[\\/#?])/",
"replacements": [
{
"regex": "/(.*)/",
"replacement": "/NONEXISTENT_PAGE"
}
]
}
],
"allowStatus": true,
"dontCompress": [
"/.*\\.ipxe$/",
"/.*\\.img$/",
"/.*\\.iso$/"
],
"enableIPSpoofing": false,
"secure": false,
"sni": {},
"disableNonEncryptedServer": false,
"disableToHTTPSRedirect": false,
"enableETag": true,
"disableUnusedWorkerTermination": false,
"rewriteDirtyURLs": true,
"errorPages": [
{
"scode": 404,
"path": "oops.html",
"host": "website.example"
}
],
"customHeadersVHost": [
{
"host": "website.example",
"headers": {
"X-Some-Header": "some-value"
}
}
],
"enableDirectoryListingVHost": [
{
"host": "website.example",
"enable": false
}
]
}
```
If you're using SVR.JS 3.14.0 or newer, you can use this configuration:
```json
{
"users": [],
"port": 80,
"pubport": 80,
"page404": "404.html",
"blacklist": [],
"nonStandardCodes": [
{
"url": "/anothersite.example/dl",
"location": "/download",
"host": "anothersite.example",
"scode": 301
},
{
"url": "/anothersite.example/downloads",
"location": "/download",
"host": "anothersite.example",
"scode": 301
}
],
"enableCompression": true,
"customHeaders": {},
"enableHTTP2": false,
"enableLogging": true,
"enableDirectoryListing": true,
"enableDirectoryListingWithDefaultHead": false,
"serverAdministratorEmail": "[no contact information]",
"stackHidden": false,
"enableRemoteLogBrowsing": false,
"exposeServerVersion": true,
"disableServerSideScriptExpose": true,
"rewriteMap": [
{
"definingRegex": "/^\\/anothersite.example\\/index(?:$|[\\/#?])/",
"host": "anothersite.example".
"replacements": [
{
"regex": "/^\\/anothersite.example\\/index/",
"replacement": "/anothersite.example/"
}
]
},
],
"allowStatus": true,
"dontCompress": [
"/.*\\.ipxe$/",
"/.*\\.img$/",
"/.*\\.iso$/"
],
"enableIPSpoofing": false,
"secure": false,
"sni": {},
"disableNonEncryptedServer": false,
"disableToHTTPSRedirect": false,
"enableETag": true,
"disableUnusedWorkerTermination": false,
"rewriteDirtyURLs": true,
"errorPages": [
{
"scode": 404,
"path": "oops.html",
"host": "website.example"
}
],
"customHeadersVHost": [
{
"host": "website.example",
"headers": {
"X-Some-Header": "some-value"
}
}
],
"enableDirectoryListingVHost": [
{
"host": "website.example",
"enable": false
}
],
"wwwrootPostfixesVHost": [
{
"host": "website.example",
"postfix": "website.example",
"skipRegex": "/^\\/.dirimages(?:$|[\\/#?]))/"
},
{
"host": "anothersite.example",
"postfix": "anothersite.example",
"skipRegex": "/^\\/.dirimages(?:$|[\\/#?]))/"
}
{
"postfix": "NONEXISTENT_SITE"
}
],
"wwwrootPostfixPrefixesVHost": [
"/cgi-bin"
]
}
```
You need to then create this directory structure in SVR.JS web root:
* cgi-bin
* website.example
* anothersite.example
* website.example
* anothersite.example
If you want to still use SVR.JS server-side JavaScript (not including SVR.JS mods implementing specific web applications) and virtual hosts simultaneously, path checks need to correspond to rewritten URLs (those processed by URL rewriting engine).
For some SVR.JS mods, path settings may correspond to URLs processed by URL rewriting engine.
It is not recommended to use global custom head and foot (_head.html_, _foot.html_, _.head_, _.foot_) with this setup, because they will apply to all virtual hosts (doesn't include custom heads and feet for directory listings [_.dirhead_, _.dirfoot_], which apply to only one directory).
### Client-initiated secure renegotiation
Client-initiated secure renegotiation may pose DoS risks. However, Node.JS (JS runtime on which SVR.JS is running on) has built-in protection against DoS attacks caused by client-initiated secure renegotiation. Such attacks can be detected by looking for _ERR_TLS_SESSION_ATTACK_ errors in server log.
## Mods
Mods in SVR.JS are custom modules that can extend the server's functionality. Using mods, you can extend SVR.JS functionality to suit your specific requirements and customize the server's behavior to handle different types of requests.
### Installing mods
To install mod to SVR.JS, copy the mod to _mods_ directory inside SVR.JS installation directory. SVR.JS searches this directory for mods, loads and executes them in alphabetical order (by mod file name). If you want have mods to be executed in specific order, add numeric prefix to mod file name, for example "_01-redbrick.cgi.2.3.3.tar.gz_" and "_00-easywaf.integration.1.1.2.tar.gz_".
### Mod format
SVR.JS mods are _tar_ archives with _gzip_ compression, they work in SVR.JS 2.x and newer
SVR.JS 1.x used custom _svrmodpack_ archives with _gzip_ compression (they work in all SVR.JS versions), but this format is **deprecated for new mods, and may be no longer supported in future versions of SVR.JS**, since _svrmodpack_ is not maintained anymore. All current SVR.JS mods are now in _tar.gz_ format. **SVR.JS 3.13.0 dropped support for _svrmodpack_.**
### Mod loading order
#### Startup
1. Search for mods
2. For each mod (sorted alphabetically by mod file name):
1. Prepare temporary directory for extracted mod contents
2. Extract mod contents
3. Initialize mod, and add mod along with mod info to list
3. Load server-side JavaScript:
1. Create mod file from server-side JavaScript
2. Initialize "mod", and add "mod" to list
#### Execution (on each server request)
1. Initialize SVR.JS variables
2. Invoke mods and server-side JavaScript (mods sorted alphabetically by mod file name)
3. Load SVR.JS main callback (if it's not affected by mods and server-side JavaScript)
### Mod files
1. _index.js_ - main script for mod
2. _mod.info_ - information about mod
3. other files necessary for the mod
### Mod development
Mods in SVR.JS have two methods:
* _callback_ - Invoked on non-CONNECT requests (includes proxy requests using GET or POST methods). Parameters (must be in this particular order, argument names given to match SVR.JS API documentation):
* _req_
* _res_
* _serverconsole_
* _responseEnd_
* _href_
* _ext_
* _uobject_
* _search_
* _defaultpage_
* _users_
* _page404_
* _head_
* _foot_
* _fd_
* _elseCallback_
* _configJSON_
* _callServerError_
* _getCustomHeaders_
* _origHref_
* _redirect_
* _parsePostData_
* _authUser_
**This method is required** (if it is not present, SVR.JS will simply return 500 Internal Server Error on all requests with error message in error stack similar to "_TypeError: modO.callback is not a function_").
* _proxyCallback_ - Invoked on CONNECT requests (used for proxying). Parameters (must be in this particular order, argument names given to match SVR.JS API documentation):
* _req_
* _socket_
* _head_
* _configJSON_
* _serverconsole_
* _elseCallback_
Required in order for function returned from _callback_ method to be invoked for request URLs beginning with "_http://_" or with "_https://_" (proxy through GET or POST method, non-proxy requests have request URLs beginning with "_/_"). **You should implement a proxy URL check in _callback_ method, if you're going to use _proxyCallback_ and _callback_ methods at once, or else your SVR.JS mod may be vulnerable to access control bypass attacks** (SVR.JS doesn't enforce URL rewriting, custom headers and non-standard codes for proxy requests to avoid interference of its access controls with proxy mods).
These methods are defined inside _Mod.prototype_ object. Both methods return a function, which will be executed in SVR.JS.
`__dirname` and _._ in `require()` function both refer to directory, to which mod contents are extracted.
The reference to file in the SVR.JS installation directory is `__dirname + "/../../../filename"` (replace `filename` with your desired file name).
Current working directory (`process.cwd()`) is SVR.JS web root.
A typical _index.js_ file for a mod may look like this:
```js
//Requires go here
function Mod() {}
Mod.prototype.callback = function callback(req, res, serverconsole, responseEnd, href, ext, uobject, search, defaultpage, users, page404, head, foot, fd, elseCallback, configJSON, callServerError, getCustomHeaders, origHref, redirect, parsePostData) {
return function () {
//Mod contents go here
if (href == "/hello.svr") {
serverconsole.resmessage("Sent Hello World message!");
res.writeHead(200, "OK", {
"Content-Type": "text/plain"
});
res.end("Hello World!");
} else {
elseCallback();
}
}
}
//OPTIONAL: proxyCallback method
//Uncomment code below, if you want to use proxyCallback method.
//But then you'll need to implement proxy request URL check for callback method.
/*
Mod.prototype.proxyCallback = function proxyCallback(req, socket, head, configJSON, serverconsole, elseCallback) {
return function () {
//Just pass elseCallback
elseCallback();
}
}
*/
module.exports = Mod; //SVR.JS mod exports
```
The _mod.info_ file (in JSON format) contains metadata about the mod, such as its name and version:
```
{
"name": "The Example Mod",
"version": "0.1.0"
}
```
## Server-side JavaScript
Another way to expand SVR.JS functionality is through server-side JavaScript located in _serverSideScript.js_ file inside SVR.JS web root (or locaten in SVR.JS installation directory if you're running SVR.JS 3.9.0 or newer, and you have set _useWebRootServerSideScript_ property to _false_). Server-side JavaScript allows you to create various web applications using JavaScript, Node.JS and SVR.JS API.
### Predefined objects
When working with server-side JavaScript in SVR.JS, you have access to several predefined objects that can greatly enhance your scripting capabilities. These objects are available for use without requiring any additional imports or installations.
* _readline_: The _readline_ library for reading input streams.
* _os_: The _os_ library for accessing operating system-related information.
* _http_: The _http_ library for handling HTTP functionality.
* _url_: The _url_ library for parsing and formatting URLs.
* _fs_: The _fs_ library for interacting with the file system.
* _path_: The _path_ library for working with file and directory paths.
* _hexstrbase64_: The _hexstrbase64_ library for converting hexadecimal strings to base64 format.
* _crypto_: The _crypto_ library for cryptographic functionality, such as generating hashes and handling encryption.
* _https_: The _https_ library, an extension of the _http_ library for handling secure HTTPS connections.
* _stream_: The _stream_ library for working with streams of data.
* _customvar1_, _customvar2_, _customvar3_, _customvar4_: Custom variables meant to be reused in multiple requests. These variables are available starting from SVR.JS version 3.0.0.
Additionally, there is an option to control the automatic execution of the _elseCallback_ function. By default, automatic execution is enabled. You can use the _disableEndElseCallbackExecute_ option to disable this behavior if needed.
By leveraging these predefined objects, you can streamline your server-side JavaScript code and build powerful applications using SVR.JS.
### Predefined methods
_See methods in SVR.JS API in non-proxy section_
Additionally SVR.JS server-side JavaScript has `filterHeaders(headers)` method, that filters out invalid request headers.
SVR.JS 3.8.0 and newer have additionally two methods:
* `checkHref(destHref)` - checks if request path name matches the _destHref_.
* `checkHostname(hostname)` - checks if host name defined in the request matches the _hostname_ parameter.
### SSJS development
`__dirname` and _._ in `require()` function both refer to _temp_ directory in SVR.JS.
Current working directory (`process.cwd()`) is SVR.JS web root.
If you want to divide server-side JavaScript into several files, you can do one of those:
* `require(process.cwd() + "/someOtherScript.js")` for script located in the web root (**it's recommended to set up 403 Forbidden or 404 Not Found non-standard code in SVR.JS configuration to prevent source code leaks**).
* `require("../someOtherScript.js")` for script located in SVR.JS installation directory.
* `require("/usr/lib/webappfiles/someOtherScript.js")` for script located in _/usr/lib/webappfiles_.
Example code:
```js
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
if (href == "/hello.svr") {
serverconsole.resmessage("Sent Hello World message!");
res.writeHead(200, "OK", {
"Content-Type": "text/plain"
});
res.end("Hello World!");
} else {
elseCallback();
}
```
### Migration to SVR.JS
If you have previously built your web application using the Node.JS http library, Express framework, or Koa framework, you can easily migrate that code to SVR.JS server-side JavaScript.
#### From Node.JS http library
For applications built with the Node.JS http library, you can simply copy the contents of the request event listener to the SVR.JS server-side JavaScript. However, make sure to consider the _disableEndElseCallbackExecute_ option to ensure proper execution flow.
```js
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
// Node.JS http library request event listener code goes here.
if(req.url == "/" && req.method == "GET") {
res.writeHead(200, "OK", {
"Content-Type": "text/plain"
});
res.end("Hello World!");
return;
}
elseCallback(); // Optionally, invoke main SVR.JS callback.
```
#### From Express Framework
If your application is built using the Express framework, you can easily migrate it to SVR.JS. You can mix Express methods with SVR.JS methods for more flexibility.
```js
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
var express = require("express");
// Other requires go here.
var app = express(); // Initialize express app
// Express application code goes here!
app.get("/", function (req, res) {
res.send("Hello World!");
});
app.use(elseCallback); // Optionally, if you want the main SVR.JS callback.
app(req, res); // Invoke Express handler
```
#### From Koa Framework
Migrating from the Koa framework to SVR.JS is also straightforward. Here's an example of how you can do it:
```js
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
var koa = require("koa");
// Other requires go here.
var app = new koa(); // Initialize Koa app
// Koa application code goes here!
app.use(function (ctx, next) {
if (ctx.method != "GET" || ctx.path != "/") {
next(); // Koa router could be used...
} else {
ctx.body = "Hello World!";
}
});
// Optionally, if you want the main SVR.JS callback (not recommended by Koa, as it passes Node.JS req and res objects).
app.use(function (ctx) {
ctx.respond = false;
elseCallback(ctx.req, ctx.res);
});
(app.callback())(req, res); // Invoke Koa handler
```
By migrating your web application to SVR.JS, you can take advantage of its features and performance enhancements, while still preserving your existing codebase.
## SVR.JS API
SVR.JS has its API for both mods and server-side JavaScript that expands its functionality. SVR.JS API extends vanilla Node.JS HTTP API.
### Error handling
When a JavaScript error is thrown outside of event callbacks, SVR.JS will return a 500 error to the client. Inside event callbacks, SVR.JS will simply crash.
#### Incorrect Error Handling:
```js
//XXX WARNING!!! IT WILL CRASH THE SVR.JS!!!
//It also contains path traversal vulnerability!
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
var headers = getCustomHeaders();
headers["Content-Type"] = "text/html; charset=utf8";
if(href == "/page.svr") {
fs.readFile(".template", function(err, data) {
if(err) throw err; //EVIL!!!
var id = uobject.query.id;
if(!id) id = "index";
if(fs.existsSync("pages/" + id + ".html")) {
fs.readFile("pages/" + id + ".html", function(err2, data2) {
2024-03-15 21:53:12 +01:00
if(err2) throw err2; //EVIL TWO!!!
res.writeHead(200,"OK", headers);
res.end(data.toString().replace("{websiteContents}",data2.toString()));
});
} else {
callServerError(404);
}
});
} else if(href == "/") {
redirect("/page.svr");
} else {
elseCallback();
}
```
Instead, you should handle errors gracefully using _callServerError_ function:
#### Correct Error Handling:
```js
//Much better!
disableEndElseCallbackExecute = true; //Without "var", else it will not work!!!
var headers = getCustomHeaders();
headers["Content-Type"] = "text/html; charset=utf8";
if(href == "/page.svr") {
if(fs.existsSync(".template")) {
fs.readFile(".template", function(err, data) {
if(err) {
callServerError(500,err);
return;
}
var id = uobject.query.id;
if(!id) id = "index";
id = id.replace(/\\/g,"/").replace(/(?:\/|^)\.\.(?=(\/|$))/g,"$1").replace(/\/+/g,"/"); //Poor mans path sanitiation
2024-03-15 21:53:12 +01:00
if(fs.existsSync("pages/" + id + ".html")) {
fs.readFile("pages/" + id + ".html", function(err2, data2) {
2024-03-15 21:53:12 +01:00
if(err2) {
callServerError(500,err2);
return;
}
res.writeHead(200,"OK", headers);
res.end(data.toString().replace("{websiteContents}",data2.toString()));
});
} else {
callServerError(404);
}
});
} else {
callServerError(500, new Error("Server is misconfigured - .template file missing"));
}
} else if(href == "/") {
redirect("/page.svr");
} else {
elseCallback();
}
```
By using `callServerError`, you can handle errors effectively and provide appropriate error responses to the client, preventing SVR.JS from crashing due to unhandled exceptions.
### Non-proxy API
This API is exposed both to mods and server-side JavaScript. This API also includes proxy requests, which don't use CONNECT method. It's possible to determine, if the request comes from the proxy, by checking if _req.url_ begins with "_http://_" or with "_https://_" (unlike non-proxy requests, for which _req.url_ begins with "_/_") like this:
```js
var isProxy = (req.url && req.url.match(/^https?:\/\//));
```
SVR.JS applies mods for request URLs beginning with "_http://_" or with "_https://_" (proxy through GET or POST method, non-proxy requests have request URLs beginning with "_/_") only if _Mod.prototype.proxyCallback_ method is present (not possible with SVR.JS server-side JavaScript).
#### _req_
_req_ object is almost same, as _req_ object in Node.JS
Differences:
* _req.socket.realRemoteAddress_ and _req.socket.realRemotePort_ will contain IP address, from which request originally went from, if request is sent through reverse proxy (for _X-Forwarded-For_ header, _req.socket.realRemotePort_ will be _null_). You can specify generic request IP variable using `var reqip = req.socket.realRemoteAddress ? req.socket.realRemoteAddress : req.socket.remoteAddress` (from SVR.JS 3.4.4)
* _req.socket.originalRemoteAddress_ and _req.socket.originalRemotePort_ will contain IP address, from which proxy request came from.
* _req.url_ refers to request URL after all processing (URL rewriting too)
#### _res_
_res_ object is almost same, as _res_ object in Node.JS
Differences:
* _res.socket.realRemoteAddress_ and _res.socket.realRemotePort_ will contain IP address, from which request originally went from, if request is sent through reverse proxy. (for _X-Forwarded-For_ header, _req.socket.realRemotePort_ will be _null_; from SVR.JS 3.4.4)
* _res.socket.originalRemoteAddress_ and _res.socket.originalRemotePort_ will contain IP address, from which proxy request came from.
* _res.writeHead_ writes into server log.
* _res.writeHead_ doesn't invoke a warning about unused status code string.
* _res.setHeader_ doesn't invoke a warning about HTTP/1.x headers being not allowed in HTTP/2.
* _res.writeHead_ called multiple times will emit a warning, instead of throwing an error, which could crash SVR.JS.
* Custom headers defined in _config.json_ are set by default.
#### _serverconsole.climessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends CLI message to server console.
#### _serverconsole.reqmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends request message to server console.
#### _serverconsole.resmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends response message to server console.
#### _serverconsole.errmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends response error message to server console.
#### _serverconsole.locerrmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends local error message to server console.
#### _serverconsole.locwarnmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends local warning message to server console.
#### _serverconsole.locmessage(message)_
Parameters:
* _message_ - message you want to send to server console (_String_)
Sends local message to server console.
#### _responseEnd(body)_
Parameters:
* _body_ - message you want to send before ending response (_String_ or _Buffer_)
Sends response message (along with custom head and foot) specified by _body_ parameter.
#### _href_
Path name of resource defined in the request. Alias for _uobject.pathname_.
#### _ext_
Extension of resource defined in the request.
#### _uobject_
Parsed _Url_ object created by _url.parse()_ method (includes parsed query string).
SVR.JS 3.3.1 and newer include hostname of the server (3.3.1 to 3.14.x use wrapper over WHATWG URL API; 3.15.0 and newer use custom URL parser), older versions don't.
2024-03-15 21:53:12 +01:00
#### _search_
Query string of URL. Alias for _uobject.search_
#### _defaultpage_
**WARNING! DEPRECATED IN SVR.JS 3.X OR NEWER**
In SVR.JS 2.x it was alias for _configJSON.defaultpage_. In SVR.JS 3.x for backward compability it's always "_index.html_".
#### _users_
**WARNING! DEPRECATED**
Alias for _configJSON.users_
#### _page404_
Alias for _configJSON.page404_
#### _head_
HTML head read from either _.head_ or _head.html_ file.
#### _foot_
HTML foot read from either _.foot_ or _foot.html_ file.
#### _fd_
**WARNING! This property has currently no use and it's reserved for new SVR.JS functions.** Currently this property is an empty string.
#### _elseCallback()_
Invokes next SVR.JS mod callback, SVR.JS server-side JavaScript callback or main SVR.JS callback.
#### _configJSON_
<small>_Added in SVR.JS 3.0.0_</small>
Parsed object of _config.json_ file.
SVR.JS 3.4.0 and newer has _version_ property, that corresponds to server version, and _productName_ property, which always is "SVR.JS".
#### _callServerError(errorCode[, extName][, stack][, ch])_
<small>_Added in SVR.JS 3.0.0_</small>
Parameters:
* _errorCode_ - HTTP error code (_Number_)
* _extName_ - extension name, which caused an error (optional; _String_)
* _stack_ - error stack (optional; _String_ or _Error_)
* _ch_ - custom HTTP headers for error (optional; _Object_)
Invokes HTTP error code. If it's unavailable, invokes 501 error code.
#### _getCustomHeaders()_
<small>_Added in SVR.JS 3.0.0_</small>
Returns: _Object_ property contains custom headers.
This methods retrieves custom headers from _config.json_ file. Returned object additionally includes _Server_ header.
#### _origHref_
<small>_Added in SVR.JS 3.0.0_</small>
Original path name before URL rewriting.
#### _redirect(dest[, isTemporary][, keepMethod][, headers])_
<small>_Added in SVR.JS 3.0.0_</small>
Parameters:
* _dest_ - destination of redirect (_String_)
* _isTemporary_ - if _true_, then redirect with 302 code. Else redirect with 301 code. When _keepMethod_ parameter is set to _true_, then redirect with 307 code, when _isTemporary_ is true or with 308 code otherwise. (optional; _Boolean_)
* _keepMethod_ - if _true_, then redirect with either 307 or 308 code. Else redirect with etiher 301 or 302 code. (optional; _Boolean_; SVR.JS 3.13.0 or later)
* _headers_ - custom HTTP headers for redirect (optional; _Object_)
Redirects HTTP client to specific destination.
#### _parsePostData([options], callback)_
<small>_Added in SVR.JS 3.0.0_</small>
Parameters:
* _options_ - options to be passed to _formidable_ (optional; _Object_)
* _callback_ - callback to execute after parsing URL. (_Function_)
* _err_ - error, which occurred in POST data parsing. If not occured, it's _null_ (_Error_ or _null_)
* _fields_ - POST fields (_Object_)
* _files_ - Files sent (_Object_)
A wrapper over _formidable_ library, which is used for parsing request bodies of POST requests.
#### _authUser_
<small>_Added in SVR.JS 3.14.2_</small>
The name of authenticated HTTP user. If the user wasn't authenticated, the property would be _null_.
If you want to check if the request is authenticated in SVR.JS versions older than 3.14.2, you can use function shown below, that checks for an applicable 401 non-standard code in the server configuration:
```js
function checkIfThereIsA401Rule() {
var actually401 = false;
function createRegex(regex) {
var regexObj = regex.split("/");
if (regexObj.length == 0) throw new Error("Invalid regex!");
var modifiers = regexObj.pop();
regexObj.shift();
var searchString = regexObj.join("/");
return new RegExp(searchString, modifiers);
}
if(configJSON.nonStandardCodes) {
configJSON.nonStandardCodes.every(function (nonscode) {
if (nonscode.scode == 401) {
if (nonscode.regex && (req.url.match(createRegex(nonscode.regex)) || href.match(createRegex(nonscode.regex)))) {
actually401 = true;
return true;
} else if (nonscode.url && (nonStandardCodes[i].url == href || (os.platform() == "win32" && nonStandardCodes[i].url.toLowerCase() == href.toLowerCase()))) {
actually401 = true;
return true;
}
}
return false;
});
}
return actually401;
}
```
### Proxy API
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
This API is exposed only to mods. It is invoked, when client connects with the server using CONNECT method.
This API was present from SVR.JS 3.0.0, however SVR.JS version older than 3.4.21 or 3.7.0 had a bug, which involves calling non-proxy callback, instead of proxy one. A workaround involves calling proxy callback over non-proxy one, when request uses CONNECT method (insert at beginning of non-proxy callback):
```js
if(!res.writeHead) {
Mod.prototype.proxyCallback(req, res, serverconsole, responseEnd, href, ext)();
return;
}
```
#### _req_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_req_ object is the same, as _req_ object in Node.JS
#### _socket_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_socket_ object is the same, as _socket_ object in Node.JS
#### _head_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_head_ object is the same, as _head_ object in Node.JS
#### _configJSON_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_See configJSON in non-proxy API_
#### _serverconsole_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_See serverconsole in non-proxy API_
#### _elseCallback()_
<small>_Added in SVR.JS 3.4.21, 3.7.0_</small>
_See elseCallback in non-proxy API_