Are you eager to get programming with Swift and Perfect? This guide will provide you with everything you need to know to run Perfect, and to create your first application.
After reading this guide, you will know:
- How to create and run an HTTP/HTTPS server and get Perfect up and running
- The prerequisite components you must install to run Perfect on either OS X or Ubuntu Linux
- How to build, test, and manage dependencies for Swift projects
- How to deploy Perfect in additional environments including Heroku, Amazon Web Services, Docker, Microsoft Azure, Google Cloud, IBM Bluemix CloudFoundry, and IBM Bluemix Docker
After you have installed a Swift 4.0 toolchain from Swift.org, open up a terminal window and type
swift --version
It will produce a message similar to this one:
Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37)
Target: x86_64-apple-macosx10.9
Make sure you are running the release version of Swift 4.0+. Perfect will not compile successfully if you are running a version of Swift that is lower than 3.0.1.
You can find out which version of Swift you will need by looking in the README of the main Perfect repo.
Everything you need is already installed.
Perfect runs in Ubuntu Linux 16.04 environments. Perfect relies on OpenSSL, libssl-dev, and uuid-dev. To install these, in the terminal, type:
sudo apt-get install openssl libssl-dev uuid-dev
When building on Linux, OpenSSL 1.0.2+ is required for this package. On Ubuntu 14 or some Debian distributions you will need to update your OpenSSL before this package will build.
Now you’re ready to build your first web application starter project.
The following will clone and build an empty starter project. It will launch a local server that will run on port 8181 on your computer:
git clone https://github.com/PerfectlySoft/PerfectTemplate.git
cd PerfectTemplate
swift build
.build/debug/PerfectTemplate
You should see the following output:
[INFO] Starting HTTP server localhost on 0.0.0.0:8181
The server is now running and waiting for connections. Access http://localhost:8181/ to see the greeting. Hit "control-c" to terminate the server.
You can view the full source code for PerfectTemplate.
Swift Package Manager (SPM) can generate an Xcode project which can run the PerfectTemplate server and provide full source code editing and debugging for your project. Enter the following in your terminal:
swift package generate-xcodeproj
Open the generated file "PerfectTemplate.xcodeproj". Ensure that you have selected the executable target and selected it to run on "My Mac". You can now run and debug the server directly in Xcode.
These example snippets show how to accomplish several common tasks that one might need to do when developing a web or REST application. In all cases, the request
and response
variables refer, respectively, to the HTTPRequest
and HTTPResponse
objects which are given to your URL handlers.
Consult the API reference for more details.
if let acceptEncoding = request.header(.acceptEncoding) {
...
}
if let foo = request.param(name: "foo") {
...
}
if let foo = request.param(name: "foo", defaultValue: "default foo") {
...
}
let foos: [String] = request.params(named: "foo")
let path = request.path
let docRoot = request.documentRoot
do {
let mrPebbles = File("\(docRoot)/mr_pebbles.jpg")
let imageSize = mrPebbles.size
let imageBytes = try mrPebbles.readSomeBytes(count: imageSize)
response.setHeader(.contentType, value: MimeType.forExtension("jpg"))
response.setHeader(.contentLength, value: "\(imageBytes.count)")
response.setBody(bytes: imageBytes)
} catch {
response.status = .internalServerError
response.setBody(string: "Error handling request: \(error)")
}
response.completed()
for (cookieName, cookieValue) in request.cookies {
...
}
let cookie = HTTPCookie(name: "cookie-name", value: "the value", domain: nil,
expires: .session, path: "/",
secure: false, httpOnly: false)
response.addCookie(cookie)
response.setHeader(.contentType, value: "application/json")
let d: [String:Any] = ["a":1, "b":0.1, "c": true, "d":[2, 4, 5, 7, 8]]
do {
try response.setBody(json: d)
} catch {
//...
}
response.completed()
This snippet uses built-in JSON encoding. Feel free to use the JSON encoder/decoder you prefer.
response.status = .movedPermanently
response.setHeader(.location, value: "http://www.perfect.org/")
response.completed()
struct Filter404: HTTPResponseFilter {
func filterBody(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
callback(.continue)
}
func filterHeaders(response: HTTPResponse, callback: (HTTPResponseFilterResult) -> ()) {
if case .notFound = response.status {
response.bodyBytes.removeAll()
response.setBody(string: "The file \(response.request.path) was not found.")
response.setHeader(.contentLength, value: "\(response.bodyBytes.count)")
callback(.done)
} else {
callback(.continue)
}
}
}
try HTTPServer(documentRoot: webRoot)
.setResponseFilters([(Filter404(), .high)])
.start(port: 8181)