Build websites with Swift.
Swiftfire is a webserver that allows the injection of HTML code from routines written with Swift.
The Swiftfire webserver can be extended with functions and services written in Swift. The services are used to process a HTTP request, and the functions are used to prepare a response by processing the requested page or file. This makes it possible to create entire websites written in nothing else but HTML, CSS and Swift. No other languages, frameworks or external services necessary, with a minor exception for openSSL for HTTPS.
To use Swiftfire as an end-user you need a MacOS computer capable of running at least MacOS 10.12.
To develop Swiftfire extensions you need Xcode as well.
Also builds and runs on Linux (Mint 19.3) with the Swift Ubuntu 18.04 download from swift.org.
Visit the Swiftfire homepage at http://swiftfire.nl for all available documentation.
Beware: In the current version 1.x Swiftfire is still experimental. It works, but as this way of building websites is still new, it has to be expected that significant changes will need to be made as we gain experience. Hence if you are following along, you should expect that new releases will necessitate some recoding, including any websites that you might be creating. Version 2.0 will be released when we are relatively certain that major recodings will no longer be needed.
How it works
This is a very high level overview of how Swiftfire can use Swift code to create websites.
Every domain that is hosted under Swiftfire implements a stack of services. By default that stack implements a static website.
For each (valid and accepted) request that arrives at the server, Swiftfire finds the stack of services to execute and does so one service after the other.
You can add your own services to modify or extend the default behaviour.
However it is much more likely that you will want to create your own functions.
Functions can be used to inject HTML code into otherwise "static" web pages. Giving them dynamic qualities.
One of the services in the stack retrieves the requested page from disk and verifies if it must be parsed. If it must be parsed it scans the page for 'functions'. Any function that is found is executed, and the result of the execution is injected into the page at the exact spot of the function. The function itself is removed.
An example for the function ".nofPageHits()".
In the HTML code we would call the function as follows:
<p>This page has been accessed .nofPageHits() times</p>
which would then be translated by Swiftfire to:
<p>This page has been accessed 59440 times</p>
or any other number of course.
The best part is, you can define and write the functions yourself.
It is even possible to create loops and use conditinal expressions:
<p>Your name is: .if($account, equal, nil) unknown .else() .show($account.name) .end()</p>
It is up to you to determine how much you want to do in Swift. For example, you could decide to have the entire landing page to be created by a function. To do that let index.sf.html exist only of:
.buildLandingPage(). And of course you have to implement the function that is registered under the name
It is fast. Depending of course on the amount and complexity of the services and functions, Swiftfire as presented here is very fast. On our server (a mac mini) the static pages are usually served in less than 2mS. Adding functions and services will increase this number of course. Still since the function calls and services refer to compiled code instead of interpreted code the speed of Swiftfire can be expected to be higher than interpreter solutions.
Oh, and it does PHP as well...
Swiftfire is a faceless webserver application. However it comes with a website that can be used for administration purposes. On initial start of the server, any request on the port on which the server listens will result in a landing page that asks the user to create an admin account and the directory in which the administration site is installed.
Once set up, access any hosted domain and append: '/serveradmin' to the url. This will return the server administrator website. Note that the login is only as secure as the protocol. Use HTTP only when accessing from within a private LAN.
When a domain is created the domain setup page can be accessed at 'domain-url/setup'.
- Builds and runs on MacOS and Linux
- Allows code injection (HTML and CSS) from functions written in Swift
- Allows website services to be implemented in Swift
- Out of the box support for static websites
- Handles multiple domains
- Integrated comment system for local storage
- Sessions are supported
- Accounts are supported
- End-user registration and lost-password supported (needs postfix)
- Integrated comment system
- Client forwarding (to other hosts or a different port on the same host)
- Integrated usage statistics (page visits)
- Blacklisting (refusal of service) on IP basis for Server and per domain
- Supports HTTP1.0 and HTTP1.1
- Supports HTTPS
- Web based interface for Swiftfire Administrator
- Custom pages for errors (for example the infamous 404 page not found)
- Logging of received headers possible
- Logging of missing pages (404)
- Supports PHP
- Multiple server administrators
- Multiple domain administrators
- Integrated with the Jekyll theme: Swifterfire-Jekyll-Theme
Download the project using git clone:
$ git clone https://github.com/Balancingrock/Swiftfire.git
Then switch to the directory containg the project:
$ cd Swiftfire
The build the project, but first make the build script executable:
$ chmod +x *.sh $ ./sf-build.sh
This should build the project without errors.
If the target macOS is before 10.14.4 then it is also necessary to install the Swift 5 Runtime Support for Command Line Tools. This will install a set of libraries into
/usr/lib/swift among which
libswiftCoreFoundation.dyLib. When you get an error message -when starting Swiftfire- complaining that this library is missing, install the Swift 5 runtime.
We could stop here, but... the project needs openSSL. And while pre-compiled versions of openSSL are provided for convenience, you should not trust this for operational use. Make sure to download and install openSSL from the original sources at openSSL.org
Directions for the installation of openSSL are in the subproject SecureSockets.
Though it is still possible to deploy Swiftfire on MacOS 10.12, this is no longer recommended due to the patches that have to be made on the openSSL source code. If the hardware is incapable of running any macOS higher than 10.12, consider switching to Linux Mint 19.3.
First follow the steps as per directions above. Perform exactly the same steps, but this time there is no need to build the project. Instead generate the xcode project:
$ swift package generate-xcodeproj
Opening the generated Xcode project update the build settings
Search Paths for the targets:
- CopensslGlue, SecureSockets, Core: Add to the build setting
Search Paths -> Header Search Pathsthe value
- CopensslGlue: Add to the build setting
Search Paths -> Library Search Pathsthe value
- CopensslGlue: Add to the build setting
Linking -> Other Linker Flagsthe value
- Swiftfire: Remove the build setting
Linking -> Other Linker Flags
<<openssl-to-be-used>> must of course be replaced by the openSSL version/compilate of your choice. See the README file in the openssl directory.
When Swiftfire is started for the first time, some configuration must be done. You may want to prepare for this by copying the
demo directories included in the repository to a different location. Though they can remain inside the project, it is less error prone to have these two websites in a different location so that potential changes will not affect an operational scenario.
In the default configuration Swiftfire will listen on port 6678 for incoming connections. Any connection attempt without domains being present will result in the return of a primitive page where the administrator ID and password must be set in addition to the location of the
Once that is done, Swiftfire can be customized by logging in as admin and using the admin pages.
Note that Swiftfire will store and expect information in the
~/Library/Application Support/Swiftfire/<<instance-root>> location after it was first started. Changes to the settings are immediately stored. The
<<instance-root>> can be used to allow multiple instances of Swiftfire to run in parallel.
Some of the logs are in *.txt format, settings are in *.json format (for which we recommend our proJSON app) and the visitor statistics are in the *.brbon format. For which there is currently no app available. The BRBON spec however can be found on github including a BRBON API. How to make the visitor statistics available is a subject of discussion.
You can of course change whatever you want, but the current source code layout was choosen for a reason. While this layout is rather new (and thus may need to change) we hope that you will only need to add to the
Services modules. Though you should leave their current contents unaffected since the correct functioning of the admin server account depends on them.
The sources for the server admin site are generated using Jekyll. If changes must be made, you will need to install Jekyll and the theme Classic-Jekyll-Theme. For more information on Jekyll see jekyllrb.com/ for more information on Classic-Jekyll-Theme see balancingrock.github.io/classic-jekyll-theme
There is a Swiftfire-Jekyll-Theme to quickly setup a (blogging) website that includes handling of user comments. Swiftfire 1.3.2 is matched by Swiftfire-Jekyll-Theme 0.2.0.
|Ascii||Ascii character definitions||link||link|
|BRBON||In-memory storage manager, fast access and load/store||link||link|
|BRUtils||General purpose definitions||link||link|
|Html||Makes creating HTML code easier||link||link|
|Http||An API for HTTP messages||link||link|
|KeyedCache||General purpose dictionary like cache||link||link|
|SecureSockets||Networking utilities that implement SSL (includes COpenSSL)||link||link|
|SwifterLog||General purpose logging utility||link||link|
|SwifterSockets||POSIX based networking interface||link||link|
|Custom||Common definitions within Swiftfire||link||link|
|Admin||Administrator code within Swiftfire||link||link|
|Core||Core code within Swiftfire||link||link|
|Functions||Predefined functions in Swiftfire||link||link|
|Services||Predefined services in Swiftfire||link||link|
|Swiftfire||Swiftfire main operation||link||link|
- Added linux (mint 19.3) compatibility
- Fixed issues 10-14
- Added global parameters starttime, runtime, timestamp and rootdir
- Integrated with new jekyll theme "Swiftfire-Jekyll-Theme" version 0.2.0
- Fixed recursive session thread bug
- Reworked the sfadmin site
- Added comment system
- Fixed (removed) warning when using xcode 11
- Fixed issue #7 (removed local FileManager instances)
- Moved getInfo and postInfo from the services.info to Request.info (in the Http library) & deleted Service.DecodePostFromUrlEncoded.swift
- Removed inout declarations for class parameters
- Fixed issue #8 (no auto saving of changes to domain and alias list & servicenames)
- Fixed issue #9 (account names with differ in case only are no longer allowed)
- Added functions for account creation by users with auto-email verification
demosite to showcase features and serve as a user website template
- Rewritten sfadmin to push all html code into html files (i.e. functions should not contain html code)
- Changed server root directory to allow multiple Swiftfire servers running concurently
- Added command line parameters to support multiple Swiftfire servers running concurrently
- Updated usage of BRBON, SwifterSockets and SecureSockets due to upgrade to Swift 5.2
- Removed dependency on Html library package
- Removed the need to save & load setup parameters
- Added additional logging to capture all changes in server parameters
- Added sfadmin sources (jekyll based)
- Separated server admin and domain admin functions (added Domain Admin accounts)
- Added support of multiple server admin accounts
- Fixed issues 1 through 6
- Documentation changes
- Visibility of keys (not needed yet but will be eventually)
- Removed name definitions for functions and replaced with strings in the place where the vars were used
- Upped to 1.0.0
Removed older history entries