github.com/dunkelstern/twohundred

HTTP 1.1 Server written in Swift without the use of Foundation, only POSIX and a small socket helper in C


License
BSD-3-Clause

Documentation

TwoHundred HTTP Server

TwoHundred is a HTTP 1.1 Server written in Swift without the use of Foundation, but a little Socket helper code in C because Grand central dispatch is missing on Linux currently.

TwoHundred is IPv4 and IPv6 capable and supports HTTP 1.1 Connection Keepalive and Pipelining.

License

TwoHundred is licensed under the BSD 3 Clause license. See LICENSE.txt for full license text.

Usage

For a example see the Demo folder. The Demo is a simple file serving HTTP server that displays the files in the current working directory and allows downloading of the listed files. (Like the good old Apache file index). No counter measures against directory traversal attacks or something other advanced is going on.

To use TwoHundred you'll need to subclass the TwoHundred main class and override the HTTP Request handling function:

import twohundred

class MyHTTPServer: TwoHundredServer {
    override func handleRequest(request: HTTPRequest) -> HTTPResponse {
        return HTTPResponse(.Ok, body: [.StringData("Hello World!")])
    }
}

To run the server just instanciate your subclass and execute the start command:

let server = MyHTTPServer(listenAddress: .Wildcard, port: 4567)
server.start()

HTTPRequest

A HTTPRequest object has the following attributes:

  • remoteIP: the remote IP address that is issuing the request
  • header: parsed HTTP request header
  • data: Body data

RequestHeader

The RequestHeader may be subscripted with a string to fetch values of the HTTP headers or you may access the following attributes:

  • headers: the parsed HTTP headers from the request
  • method: HTTP method that was called
  • version: HTTP version the client used
  • url: the URL string that was requested. Get parameters and fragments are stripped off
  • getParameters: list of get parameters from the url
  • fragment: fragment (part after the #) if one was included or empty string

HTTPResponse

The HTTPResponse object is instanciated by you to return an appropriate response to the remote client. You probably want to subclass this to perform specialized responses (like a XML or JSON response).

A response is constructed of at least a HTTP status code, but has some optional initializer parameters:

  • statusCode: the first parameter, has no parameter name and is required, the response code
  • body: Array of SocketData objects that will be concatenated to build the response. You may mix and match different SocketData types like you want to
  • headers: Additional headers to send with the response, some headers are autogenerated (like Content-Length)
  • contentType: what content type to send (overrides a Content-Type header set previously)

You may add headers or body elements after initialization. Furthermore you can use the setCookie convenience function so you won't have to generate that rather complex thing by yourself.

HTTPHeader

Just a fancy tuple, in future some helper functions may be included here.

SocketData

The SocketData enum is used to queue data to be send by a socket. This data may be a simple String an array of UInt8 or even a filename of a file on disk that has to be streamed out to the remote client.

Just set the associated data when initializing an instance:

let stringData = SocketData.StringData("Hello World")
let data       = SocketData.Data([ 1, 2, 3, 4, 5])
let fileData   = SocketData.File("path/to/file/on/disk.dat")

Other helpers

URL en/decoding strings

The String type has been extended with urlEncodedString() and urlDecodedString() to facilitate percent en/decoding for usage of strings in URLs.