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 ofSocketData
objects that will be concatenated to build the response. You may mix and match differentSocketData
types like you want to -
headers
: Additional headers to send with the response, some headers are autogenerated (likeContent-Length
) -
contentType
: what content type to send (overrides aContent-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.