A new framework for building web applications in Swift is available to the public. The SWSGI framework is a lightweight, modular and open-source solution that leverages the power of WebKit’s SWSGI library.
The swifter library is a lightweight web framework in Swift. It’s based on SWSGI and it has been optimized for speed.
Swift-based super-lightweight web framework based on SWSGI
Features
- Extremely light weight
- API mimicking tool that is simple to use and intended for UI automated testing.
- Based on SWSGI, it may be used with any HTTP server, not only Embassy.
- Middleware response handlers that are simple to combine
- Friendly to async
Example
Here’s an example of how to mimic API endpoints using the HTTP servers Ambassador and Embassy.
importation Embassy importation Let loop = try, EnvoyAmbassador! SelectorEventLoop(selector: try! ), SelectorEventLoop(selector: try! ), SelectorE let router = Router() let server = DefaultHTTPServer) let queueSelector()) let queueSelector()) let queueSelector()) let queueSelector()) let queueSelector()) let queueSele (eventLoop: loop, port: 8080, app: router.app) DelayResponse(JSONResponse(handler: -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> -> Any in return [ [“id”: “01”, “name”: “john”], [“id”: “02”, “name”: “tom”] ] )) server.start(); loop.runForever; server.start(); server.start(); server.start(); server.start(); server ()
Then open a browser and go to http://[::1]:8080/api/v2/users, or use an HTTP client to GET the URL and check what’s there.
[ “id” : “01”, “name” : “john”, “id” : “02”, “name” : “tom” ] [ “id” : “02”, “name” : “tom” ]
Router
You may map various paths to different WebApps using the Router. To route path /api/v2/users to our response handler, just set the appropriate path with the WebApp as the value, as seen in the previous example.
let router = Router() let router[“/api/v2/users”] = DelayResponse(JSONResponse(handler: -> -> -> -> -> -> -> -> -> -> -> -> -> -> [ [“id”: “01”, “name”: “john”], [“id”: “02”, “name”: “tom”] ] )
Pass router.app to the HTTP server as the SWSGI interface. When the visit path cannot be identified, the router is used. The notFoundResponse will be utilized, which just returns 404. You may modify the not found behavior by overwriting the notFoundResponse.
You may also use a regular expression to map URLs. You could, for example, write this.
let router = Router() let router[“/api/v2/users/([0-9]+)”] = DelayResponse(JSONResponse(handler: environ -> Any in let captures = environ[“ambassador.router captures”] as! [String] return [“id”: captures[0], “name”: “john”])
All queries with a URL that matches the regular expression /api/v2/users/([0-9]+) will be redirected here. All match groups will be sent into the environment as an array of string with the key ambassador.router captures.
DataResponse
DataResponse is a utility for returning data. For instance, if you want an endpoint to return the status code 500, you may do so.
DataResponse[“/api/v2/return-error”] = router[“/api/v2/return-error”] (statusCode: 500, statusMessage: “server error”)
By default, the status code is 200 OK, and the content type is application/octet-stream; however, all of these may be changed using init parameters. Custom headers and a handler for returning the data are also options. Consider the following scenario:
router[“/api/v2/xml”] = DataResponse( 201, statusMessage: “created”, contentType: “application/xml”, headers: [(“X-Foo-Bar”, “My header”)] Data(“who uses xml nowadays?”.utf8) -> environ -> Data(“who uses xml nowadays?”.utf8)
You may also use another init that comes with an additional sendData function as an argument if you want to send the body back in an async way.
(environ, sendData) in sendData(Data(“who uses xml nowadays?”.utf8)) in router[“/api/v2/xml”]] = DataResponse( statusCode: 201, statusMessage: “created”, contentType: “application/xml”, headers: [(“X-Foo-Bar”, “My header”)])
Please keep in mind that, unlike SWSGI’s sendBody, sendData only wants to be called once with the whole chunk of data.
JSONResponse
Almost similar to DataResponse, with the exception that it accepts Any instead of bytes and dumps the object in JSON format before returning it. Consider the following scenario:
router[“/api/v2/users”] -> JSONResponse() = JSONResponse() = JSONResponse() = JSONRespons [ [“id”: “01”, “name”: “john”], [“id”: “02”, “name”: “tom”] ]
DelayResponse
DelayResponse is a decorator response that temporarily delays a specified response. In the actual world, network delay will always exist; DelayResponse is an excellent tool for simulating network latency. Simply do to postpone an answer.
DelayResponse(JSONResponse(handler: -> Any in return [ [“id”: “01”, “name”: “john”], [“id”: “02”, “name”: “tom”] ] )) router[“/api/v2/users”] = DelayResponse(JSONResponse(handler: -> Any in return [ [“id”:
It delays the answer at random by default. The delay parameter may be used to change it. For example, if you want to postpone it for 10 seconds, you may do it here.
[“/api/v2/users”] = DelayResponse(JSONResponse(handler: -> Any in return [ [“id”: “01”, “name”: “john”], [“id”: “02”, “name”: “tom”] ], delay:.delay(10))
There are a variety of delay choices available.
- .assorted (min: TimeInterval, max: TimeInterval) It’s also the default as far as delay is concerned. arbitrary (min: 0.1, max: 3)
- .pause (seconds: TimeInterval) pause for a specified amount of time
- Never, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever, ever
- .no delay, i.e. the answer will be given right away.
DataReader
Use the swsgi.input function in the SWSGI environ parameter to read the POST body or any other HTTP body from the request. For instance, you might do it this way.
enviroment -> router[“/api/v2/users”] = JSONResponse() let input = environ[“swsgi.input”] any in as! SWSGIInput data in SWSGIInput data in SWSGIInput data in SWSGIInput data in SWSGIInput data in SWSGIInput data in SWSGIInput
It’s not difficult to accomplish, however the data comes in in a stream, similar to
- “the first bite”
- “the second sliver”
- ….
- ‘” (empty data array indicates EOF)
Most of the time, you won’t want to deal with the data stream manually. DataReader may be used to wait for all data to be received and process it all at once. As an example,
router[“/api/v2/users”] environ -> JSONResponse() let input = environ[“swsgi.input”] any in as! data in SWSGIInput DataReader.read(input) SWSGIInput DataReader.read(input) SWSGIInput DataReader.read(input) SWSGIInput DataReader.read(input) SWSGIInput
JSONReader
JSONReader, like DataReader, not only reads the whole block of data, but also parses it into JSON format. Here’s how it’s done.
router[“/api/v2/users”] environ -> JSONResponse() let input = environ[“swsgi.input”] any in as! JSONReader.read(input) SWSGIInput json in / handle the json object here SWSGIInput JSONReader.read(input) SWSGIInput JSONReader.read(input) SWSGIInput JSONReader.read(input) S
URLParametersReader
URLParametersReader waits for all input to arrive before parsing it into URL encoding parameters, such as foo=bar&eggs=spam. The arguments will be provided as an array of key-value pairs in the form of a key-value pair (String, String).
router[“/api/v2/users”] environ -> JSONResponse() let input = environ[“swsgi.input”] any in as! URLParametersReader.read(input) SWSGIInput params in / handle the params object here SWSGIInput URLParametersReader.read(input) SWSGIInput URLParametersReader.read(input) SWSGIInput URLParametersReader.
URLParametersReader is another option. If you wish to parse the URL encoded parameter string, use parseURLParameters. Just do it as you normally would.
params = URLParametersReader.parseURLParameters(“foo=bar&eggs=spam”) let params = URLParametersReader.parseURLParameters(“foo=bar&eggs=spam”)
Install
CocoaPods
Add Embassy to your Podfile to install using CocoaPod:
‘> 4.0’, pod ‘EnvoyAmbassador’
Carthage
Add Ambassador to your Cartfile to install using Carthage:
4.0 github “envoy/Ambassador”
Please note that Ambassador should be imported instead of EnvoyAmbassador. Because the term Ambassador was already used, we use EnvoyAmbassador for Cocoapods.
Package Manager is a program that allows you to manage
To do so, go to Package and add the repo. swiftly, as in:
let package = Package( name: “AmbassadorExample”, dependencies: [.package(url: “https://github.com/envoy/Ambassador.git”, from: “4.0.0”), ] ) import PackageDescription let package = Package( name: “AmbassadorExample”, dependencies: [.package(url: “https://github.com/envoy/Ambassador.git”, from: “4.0.0”),
GitHub
https://github.com/envoy/Ambassador
Vapor is a web framework in Swift that is based on SWSGI. It’s super lightweight and can be used for server-side rendering of HTML pages, REST APIs, and more. Reference: vapor 4 swift.
Related Tags
- swift web server
- swift http server
- https server swift
- envoy ambassador difference
- ambassador and envoy