While Swiftfire is capable of servicing most websites out-of-the-box, it is possible to add services to the domains without a deep understanding of Swiftfire itself.

Adding a service consists of three steps:

  1. Create a service
  2. Register the service
  3. Assign the service to one or more domains

Creating a service

Each HTTP request results in the activation of a chain of services.

Each service can implement some part of a webserver response.

For example, the first default service is called “Blacklist”. This service checks if the client is on a blacklist, i.e. a list of clients that are not allowed to access to that domain. If this service finds a match, it will tell the service chain handler to stop servicing the request and terminate the chain.

Each service has the same signature:

typealias Signature = (
	_ header: HttpHeader,
	_ body: Data?,
	_ connection: Connection,
	_ domain: Domain,
	_ chainInfo: inout Service.ChainInfo,
	_ response: inout Service.Response
	) -> Service.Result

The parameters are:

header: The HTTP header abstracted into a class that allows for easy access to the field elements.

body: The data that associated the request, may be nil.

connection: A connection object that o.a. handles the transfer to/from the client.

domain: A reference to the domain for which the request was made.

chainInfo: A dictionary for communication between services.

response: The response to be send back to the client.

Return value: Indicates if the response chain should continue with the next service in the chain, or if it should abort chain processing. Chain processing should never be aborted, except in specific cases (for example blacklist) or when an error is detected that prevents further processing.

Registering the service

The services are registered in “Service.Registration.swift” by the following code (example):

private let blacklist = "Abort if client IP is in blacklist"
private let onlyHttp10OrHttp11 = "Only HTTP 1.0 / 1.1 requests"
private let onlyGetOrPost = "Only GET / POST requests"
private let getResourcePathFromUrl = "Get resource path from request URL"
private let getFileAtResourcePath = "Get file at resource path"

func registerDomainServices() {
    services.register(name: blacklist, closure: ds_blacklist)
    services.register(name: onlyHttp10OrHttp11, closure: ds_onlyHttp10or11)
    services.register(name: onlyGetOrPost, closure: ds_onlyGetOrPost)
    services.register(name: getResourcePathFromUrl, closure: ds_getResourcePathFromUrl)
    services.register(name: getFileAtResourcePath, closure: ds_getFileAtResourcePath)
}

To add a service, create a new name for it, and add the service to the list. The sequence is not important, as that will be determined by the next step.

Assigning a service to a domain

Services are assigned to a domain using the serveradmin website. After logging in, select under the Domains menu the domain for which you want to organize the services.

Scroll down to the Services table, enable services by checking the ‘Used’ checkbox, and organize their sequence by assigning priority numbers (0 = first in line).