let loop = try! SelectorEventLoop(selector: try! KqueueSelector())
let server = DefaultHTTPServer(eventLoop: loop, port: 8080) {
(
environ: [String: Any],
startResponse: ((String, [(String, String)]) -> Void),
sendBody: ((Data) -> Void)
) in
// Start HTTP response
startResponse("200 OK", [])
let pathInfo = environ["PATH_INFO"]! as! String
sendBody(Data("the path you're visiting is \(pathInfo.debugDescription)".utf8))
// send EOF
sendBody(Data())
}
// Start HTTP server to listen on the port
try! server.start()
// Run event loop
loop.runForever()
Then you can visit http://[::1]:8080/foo-bar in the browser and see
the path you're visiting is "/foo-bar"
By default, the server will be bound only to the localhost interface (::1) for security reasons. If you want to access your server over an external network, you’ll need to change the bind interface to all addresses:
let server = DefaultHTTPServer(eventLoop: loop, interface: "::", port: 8080)
Async Event Loop
To use the async event loop, you can get it via key embassy.event_loop in environ dictionary and cast it to EventLoop. For example, you can create an SWSGI app which delays sendBody call like this
Please notice that functions passed into SWSGI should be only called within the same thread for running the EventLoop, they are all not threadsafe, therefore, you should not use GCD for delaying any call. Instead, there are some methods from EventLoop you can use, and they are all threadsafe
call(callback: (Void) -> Void)
Call given callback as soon as possible in the event loop
Schedule given callback to withDelay seconds then call it in the event loop.
call(atTime: Date, callback: (Void) -> Void)
Schedule given callback to be called at atTime in the event loop. If the given time is in the past or zero, this methods works exactly like call with only callback parameter.
What’s SWSGI (Swift Web Server Gateway Interface)?
SWSGI is a hat tip to Python’s WSGI (Web Server Gateway Interface). It’s a gateway interface enables web applications to talk to HTTP clients without knowing HTTP server implementation details.
It’s a dictionary contains all necessary information about the request. It basically follows WSGI standard, except wsgi.* keys will be swsgi.* instead. For example:
To read request from body, you can use swsgi.input, for example
let input = environ["swsgi.input"] as! SWSGIInput
input { data in
// handle the body data here
}
An empty Data will be passed into the input data handler when EOF
reached. Also please notice that, request body won’t be read if swsgi.input
is not set or set to nil. You can use swsgi.input as bandwidth control, set
it to nil when you don’t want to receive any data from client.
Some extra Embassy server specific keys are
embassy.connection - HTTPConnection object for the request
embassy.event_loop - EventLoop object
embassy.version - Version of embassy as a String, e.g. 3.0.0
startResponse
Function for starting to send HTTP response header to client, the first argument is status code with message, e.g. “200 OK”. The second argument is headers, as a list of key value tuple.
startResponse can only be called once per request, extra call will be simply ignored.
sendBody
Function for sending body data to client. You need to call startResponse first in order to call sendBody. If you don’t call startResponse first, all calls to sendBody will be ignored. To send data, here you can do
sendBody(Data("hello".utf8))
To end the response data stream simply call sendBody with an empty Data.
sendBody(Data())
Install
CocoaPods
To install with CocoaPod, add Embassy to your Podfile:
pod 'Embassy', '~> 4.1'
Carthage
To install with Carthage, add Embassy to your Cartfile:
github "envoy/Embassy" ~> 4.1
Package Manager
Add it this Embassy repo in Package.swift, like this
Embassy
Super lightweight async HTTP server in pure Swift.
Please read: Embedded web server for iOS UI testing.
See also: Our lightweight web framework Ambassador based on Embassy
Features
Example
Here’s a simple example shows how Embassy works.
Then you can visit
http://[::1]:8080/foo-bar
in the browser and seeBy default, the server will be bound only to the localhost interface (::1) for security reasons. If you want to access your server over an external network, you’ll need to change the bind interface to all addresses:
Async Event Loop
To use the async event loop, you can get it via key
embassy.event_loop
inenviron
dictionary and cast it toEventLoop
. For example, you can create an SWSGI app which delayssendBody
call like thisPlease notice that functions passed into SWSGI should be only called within the same thread for running the
EventLoop
, they are all not threadsafe, therefore, you should not use GCD for delaying any call. Instead, there are some methods fromEventLoop
you can use, and they are all threadsafecall(callback: (Void) -> Void)
Call given callback as soon as possible in the event loop
call(withDelay: TimeInterval, callback: (Void) -> Void)
Schedule given callback to
withDelay
seconds then call it in the event loop.call(atTime: Date, callback: (Void) -> Void)
Schedule given callback to be called at
atTime
in the event loop. If the given time is in the past or zero, this methods works exactly likecall
with only callback parameter.What’s SWSGI (Swift Web Server Gateway Interface)?
SWSGI is a hat tip to Python’s WSGI (Web Server Gateway Interface). It’s a gateway interface enables web applications to talk to HTTP clients without knowing HTTP server implementation details.
It’s defined as
environ
It’s a dictionary contains all necessary information about the request. It basically follows WSGI standard, except
wsgi.*
keys will beswsgi.*
instead. For example:To read request from body, you can use
swsgi.input
, for exampleAn empty Data will be passed into the input data handler when EOF reached. Also please notice that, request body won’t be read if
swsgi.input
is not set or set to nil. You can useswsgi.input
as bandwidth control, set it to nil when you don’t want to receive any data from client.Some extra Embassy server specific keys are
embassy.connection
-HTTPConnection
object for the requestembassy.event_loop
-EventLoop
objectembassy.version
- Version of embassy as a String, e.g.3.0.0
startResponse
Function for starting to send HTTP response header to client, the first argument is status code with message, e.g. “200 OK”. The second argument is headers, as a list of key value tuple.
To response HTTP header, you can do
startResponse
can only be called once per request, extra call will be simply ignored.sendBody
Function for sending body data to client. You need to call
startResponse
first in order to callsendBody
. If you don’t callstartResponse
first, all calls tosendBody
will be ignored. To send data, here you can doTo end the response data stream simply call
sendBody
with an empty Data.Install
CocoaPods
To install with CocoaPod, add Embassy to your Podfile:
Carthage
To install with Carthage, add Embassy to your Cartfile:
Package Manager
Add it this Embassy repo in
Package.swift
, like thisYou can read this example project here.