-
Notifications
You must be signed in to change notification settings - Fork 30
/
XcodeServer.swift
157 lines (121 loc) · 6.11 KB
/
XcodeServer.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// XcodeServer.swift
// Buildasaur
//
// Created by Honza Dvorsky on 14/12/2014.
// Copyright (c) 2014 Honza Dvorsky. All rights reserved.
//
import Foundation
import BuildaUtils
// MARK: XcodeServer Class
public class XcodeServer : CIServer {
public let config: XcodeServerConfig
let endpoints: XcodeServerEndpoints
public init(config: XcodeServerConfig, endpoints: XcodeServerEndpoints) {
self.config = config
self.endpoints = endpoints
super.init()
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let delegate: NSURLSessionDelegate = self
let queue = NSOperationQueue.mainQueue()
let session = NSURLSession(configuration: sessionConfig, delegate: delegate, delegateQueue: queue)
self.http.session = session
}
}
// MARK: NSURLSession delegate implementation
extension XcodeServer : NSURLSessionDelegate {
var credential: NSURLCredential? {
if
let user = self.config.user,
let password = self.config.password {
return NSURLCredential(user: user, password: password, persistence: NSURLCredentialPersistence.None)
}
return nil
}
public func URLSession(session: NSURLSession, didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
var disposition: NSURLSessionAuthChallengeDisposition = .PerformDefaultHandling
var credential: NSURLCredential?
if challenge.previousFailureCount > 0 {
disposition = .CancelAuthenticationChallenge
} else {
switch challenge.protectionSpace.authenticationMethod {
case NSURLAuthenticationMethodServerTrust:
credential = NSURLCredential(forTrust: challenge.protectionSpace.serverTrust!)
default:
credential = self.credential ?? session.configuration.URLCredentialStorage?.defaultCredentialForProtectionSpace(challenge.protectionSpace)
}
if credential != nil {
disposition = .UseCredential
}
}
completionHandler(disposition, credential)
}
}
// MARK: Header constants
let Headers_APIVersion = "X-XCSAPIVersion"
let SupportedAPIVersion: Int = 6 //will change with time, this codebase supports this version
// MARK: XcodeServer API methods
public extension XcodeServer {
private func verifyAPIVersion(response: NSHTTPURLResponse) -> NSError? {
guard let headers = response.allHeaderFields as? [String: AnyObject] else {
return Error.withInfo("No headers provided in response")
}
guard let apiVersionString = headers[Headers_APIVersion] as? String else {
return Error.withInfo("Couldn't find API version Int in headers")
}
guard let apiVersion = Int(apiVersionString) else {
return Error.withInfo("Couldn't find API version Int in headers")
}
if SupportedAPIVersion != apiVersion {
var common = "Version mismatch: response from API version \(apiVersion), but we support version \(SupportedAPIVersion). "
if apiVersion > SupportedAPIVersion {
common += "You're using a newer Xcode Server than we support. Please visit https://github.com/czechboy0/XcodeServerSDK to check whether there's a new version of the SDK for it."
} else {
common += "You're using an old Xcode Server which we don't support any more. Please look for an older version of the SDK at https://github.com/czechboy0/XcodeServerSDK or consider upgrading your Xcode Server to the current version."
}
return Error.withInfo(common)
}
//all good
return nil
}
/**
Internal usage generic method for sending HTTP requests.
- parameter method: HTTP method.
- parameter endpoint: API endpoint.
- parameter params: URL paramaters.
- parameter query: URL query.
- parameter body: POST method request body.
- parameter completion: Completion.
*/
internal func sendRequestWithMethod(method: HTTP.Method, endpoint: XcodeServerEndpoints.Endpoint, params: [String: String]?, query: [String: String]?, body: NSDictionary?, completion: HTTP.Completion) {
if let request = self.endpoints.createRequest(method, endpoint: endpoint, params: params, query: query, body: body) {
self.http.sendRequest(request, completion: { (response, body, error) -> () in
//TODO: fix hack, make completion always return optionals
let resp: NSHTTPURLResponse? = response
guard let r = resp else {
let e = error ?? Error.withInfo("Nil response")
completion(response: nil, body: body, error: e)
return
}
if let versionError = self.verifyAPIVersion(r) {
completion(response: response, body: body, error: versionError)
return
}
if case (200...299) = r.statusCode {
//pass on
completion(response: response, body: body, error: error)
} else {
//see if we haven't received a XCS failure in headers
if let xcsStatusMessage = r.allHeaderFields["X-XCSResponse-Status-Message"] as? String {
let e = Error.withInfo(xcsStatusMessage)
completion(response: response, body: body, error: e)
} else {
completion(response: response, body: body, error: error)
}
}
})
} else {
completion(response: nil, body: nil, error: Error.withInfo("Couldn't create Request"))
}
}
}