Last active
February 11, 2017 12:57
-
-
Save ilyapuchka/c9c3efb405e30207e6dd3003df3ec4c9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
import Ambassador | |
import Embassy | |
class EmbassyRedirectUITests: XCTestCase { | |
var app: XCUIApplication! | |
var router: Router! | |
private var eventLoop: EventLoop! | |
private var server: HTTPServer! | |
private var eventLoopThreadCondition: NSCondition! | |
private var eventLoopThread: Thread! | |
func startHTTPServer() { | |
self.eventLoop = try! SelectorEventLoop(selector: try! KqueueSelector()) | |
self.router = Router() | |
self.router.notFoundResponse = RedirectResponse(scheme: "http", host: "httpbin.org", queryOverride: [:]) | |
let server = DefaultHTTPServer(eventLoop: self.eventLoop, port: 8080, app: self.router.app) | |
server.logger.add(handler: PrintLogHandler()) | |
self.server = server | |
try! self.server.start() | |
self.eventLoopThreadCondition = NSCondition() | |
self.eventLoopThread = Thread(target: self, selector: #selector(self.runEventLoop), object: nil) | |
self.eventLoopThread.start() | |
} | |
func stopHTTPServer() { | |
self.server.stop() | |
self.eventLoopThreadCondition.lock() | |
self.eventLoop.stop() | |
while self.eventLoop.running { | |
if !self.eventLoopThreadCondition.wait(until: Date().addingTimeInterval(10)) { | |
fatalError("Join eventLoopThread timeout") | |
} | |
} | |
} | |
@objc func runEventLoop() { | |
self.eventLoop.runForever() | |
self.eventLoopThreadCondition.lock() | |
self.eventLoopThreadCondition.signal() | |
self.eventLoopThreadCondition.unlock() | |
} | |
override func setUp() { | |
super.setUp() | |
startHTTPServer() | |
continueAfterFailure = false | |
app = XCUIApplication() | |
app.launch() | |
} | |
override func tearDown() { | |
super.tearDown() | |
app.terminate() | |
stopHTTPServer() | |
} | |
func testExample() { | |
_ = expectation(description: "") | |
waitForExpectations(timeout: 5, handler: nil) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Embassy | |
import Ambassador | |
import Foundation | |
struct RedirectResponse: WebApp { | |
let host: String | |
let scheme: String | |
let queryOverride: [String: String] | |
init(scheme: String, host: String, queryOverride: [String: String]) { | |
self.host = host | |
self.scheme = scheme | |
self.queryOverride = queryOverride | |
} | |
func urlRequest(_ environ: [String: Any]) -> URLRequest { | |
var environ = environ | |
environ["HTTP_HOST"] = nil | |
var components = URLComponents() | |
components.scheme = scheme | |
components.host = host | |
components.path = environ["PATH_INFO"] as! String | |
components.query = environ["QUERY_STRING"] as? String | |
var url = components.url! | |
components = URLComponents(url: url, resolvingAgainstBaseURL: false)! | |
components.queryItems = components.queryItems?.map({ (item) in | |
var item = item | |
item.value = queryOverride[item.name] ?? item.value | |
return item | |
}) | |
url = components.url! | |
//All http headers are fucked up at this point... | |
var headers: [String: String] = [:] | |
for (key, value) in environ { | |
guard key.hasPrefix("HTTP_") else { continue } | |
let key = String(key.characters.dropFirst("HTTP_".characters.count)).replacingOccurrences(of: "_", with: "-") | |
headers[key] = value as? String | |
} | |
//URLSession will automatically decompress data but Content-Encoding reponse header will be "gzip", | |
//so we request content as it is so that it can be correcty read by client | |
headers["Accept-Encoding"] = "identity" | |
var request = URLRequest(url: url) | |
request.httpMethod = environ["REQUEST_METHOD"] as? String | |
request.allHTTPHeaderFields = headers | |
return request | |
} | |
public func app(_ environ: [String : Any], startResponse: @escaping ((String, [(String, String)]) -> Swift.Void), sendBody: @escaping ((Data) -> Swift.Void)) { | |
var request = urlRequest(environ) | |
let input = environ["swsgi.input"] as! SWSGIInput | |
DataReader.read(input) { data in | |
do { | |
print(try JSONSerialization.jsonObject(with: data, options: [])) | |
} catch {} | |
request.httpBody = data | |
URLSession.shared.dataTask(with: request) { (_data, _response, error) in | |
let response = _response as! HTTPURLResponse | |
let statusCode = response.statusCode | |
let headers = response.allHeaderFields.map({ ($0 as! String, $1 as! String) }) | |
startResponse("\(statusCode)", headers) | |
if !data.isEmpty { | |
sendBody(data) | |
} | |
sendBody(Data()) | |
}.resume() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class ViewController: UIViewController { | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
var request = URLRequest(url: URL(string: "http://localhost:8080/post")!) | |
request.httpMethod = "POST" | |
request.httpBody = try? JSONSerialization.data(withJSONObject: ["key": "value"], options: []) | |
let task = URLSession.shared.dataTask(with: request) { (data, url, error) in | |
if let data = data, !data.isEmpty { | |
do { | |
try print(JSONSerialization.jsonObject(with: data, options: [])) | |
} catch { | |
print("\(error)") | |
} | |
} else { | |
print("empty data") | |
} | |
} | |
task.resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment