Skip to content

Commit

Permalink
swift: update demos to use direct API (#349)
Browse files Browse the repository at this point in the history
**This is a working end-to-end iOS implementation using Envoy Mobile as a library!**

Depends on #312 and #353.

Updates our Swift example app to use the Envoy Mobile direct interfaces rather than using `URLSession` and Envoy as a listener.

Note: For now, we are no longer showing the text response of the response body due to the fact that the underlying implementation is not yet complete for bodied requests (headers-only).

Signed-off-by: Michael Rebello <me@michaelrebello.com>

![Simulator Screen Shot - TestDevice - 2019-08-20 at 13 57 44](https://user-images.githubusercontent.com/2643476/63383898-8f466280-c352-11e9-8c2e-944efda59ea2.png)
  • Loading branch information
rebello95 authored Aug 20, 2019
1 parent a098e03 commit 1ba8309
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 50 deletions.
5 changes: 1 addition & 4 deletions examples/swift/hello_world/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import Envoy
import UIKit

@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate {
private let envoy = try! EnvoyBuilder().build()

var window: UIWindow?

func application(
Expand All @@ -15,8 +12,8 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
window.rootViewController = ViewController()
window.makeKeyAndVisible()
self.window = window
NSLog("Finished launching!")

NSLog("Finished launching!")
return true
}
}
85 changes: 39 additions & 46 deletions examples/swift/hello_world/ViewController.swift
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import Envoy
import UIKit

private let kCellID = "cell-id"
// swiftlint:disable:next force_unwrapping
private let kURL = URL(string: "http://localhost:9001/api.lyft.com/static/demo/hello_world.txt")!
private let kRequestAuthority = "s3.amazonaws.com"
private let kRequestPath = "/api.lyft.com/static/demo/hello_world.txt"
private let kRequestScheme = "http"

final class ViewController: UITableViewController {
private let session: URLSession = {
let configuration = URLSessionConfiguration.default
configuration.urlCache = nil
configuration.timeoutIntervalForRequest = 10
return URLSession(configuration: configuration)
}()
private var requestCount = 0
private var results = [Result<Response, RequestError>]()
private var timer: Timer?
private var envoy: Envoy?

override func viewDidLoad() {
super.viewDidLoad()
do {
NSLog("Starting Envoy...")
self.envoy = try EnvoyBuilder()
.build()
} catch let error {
NSLog("Starting Envoy failed: \(error)")
}

NSLog("Started Envoy, beginning requests...")
self.startRequests()
}

Expand All @@ -34,47 +40,34 @@ final class ViewController: UITableViewController {
}

private func performRequest() {
self.requestCount += 1
let requestID = self.requestCount
var request = URLRequest(url: kURL)
request.addValue("s3.amazonaws.com", forHTTPHeaderField: "host")

// Note that the request is sent to the envoy thread listening locally on port 9001.
NSLog("Starting request to '\(kURL.path)'")
self.session.dataTask(with: request) { [weak self] data, response, error in
DispatchQueue.main.async {
self?.handle(response: response, with: data, error: error, id: requestID)
}
}.resume()
}

private func handle(response: URLResponse?, with data: Data?, error: Error?, id: Int) {
if let error = error {
return self.add(result: .failure(RequestError(id: id, message: "\(error)")))
}

guard let response = response as? HTTPURLResponse, let data = data else {
return self.add(result: .failure(RequestError(id: id, message: "missing response data")))
guard let envoy = self.envoy else {
NSLog("Failed to start request - Envoy is not running")
return
}

guard response.statusCode == 200 else {
let error = RequestError(id: id, message: "failed with status \(response.statusCode)")
return self.add(result: .failure(error))
}

guard let body = String(data: data, encoding: .utf8) else {
return self.add(result: .failure(RequestError(id: id, message: "failed to deserialize body")))
}
self.requestCount += 1
NSLog("Starting request to '\(kRequestPath)'")

let untypedHeaders = response.allHeaderFields
let headers = Dictionary(uniqueKeysWithValues: untypedHeaders.map
{ header -> (String, String) in
return (header.key as? String ?? String(describing: header.key), "\(header.value)")
})
let requestID = self.requestCount
let request = RequestBuilder(method: .get, scheme: kRequestScheme,
authority: kRequestAuthority,
path: kRequestPath).build()
let handler = ResponseHandler()
.onHeaders { [weak self] headers, statusCode, _ in
NSLog("Response status (\(requestID)): \(statusCode)\n\(headers)")
self?.add(result: .success(Response(id: requestID, body: "Status: \(statusCode)",
serverHeader: headers["server"]?.first ?? "")))
}
.onData { data, _ in
NSLog("Response data (\(requestID)): \(data.count) bytes")
}
.onError { [weak self] in
NSLog("Error (\(requestID)): Request failed")
self?.add(result: .failure(RequestError(id: requestID,
message: "failed within Envoy library")))
}

// Deserialize the response, which will include a `Server` header set by Envoy.
NSLog("Response:\n\(data.count) bytes\n\(body)\n\(headers)")
self.add(result: .success(Response(id: id, body: body, serverHeader: headers["Server"] ?? "")))
envoy.sendUnary(request, handler: handler)
}

private func add(result: Result<Response, RequestError>) {
Expand Down Expand Up @@ -102,7 +95,7 @@ final class ViewController: UITableViewController {
switch result {
case .success(let response):
cell.textLabel?.text = "[\(response.id)] \(response.body)"
cell.detailTextLabel?.text = "'Server' header: \(response.serverHeader)"
cell.detailTextLabel?.text = "'server' header: \(response.serverHeader)"

cell.textLabel?.textColor = .black
cell.detailTextLabel?.textColor = .black
Expand Down

0 comments on commit 1ba8309

Please sign in to comment.