如何获得Xcode服务器代码覆盖率api JSON响应
问题描述:
当我尝试通过传递集成ID来访问Xcode服务器代码覆盖率API而不是JSON响应时,它直接下载.bz2文件。我想使用此API在我的自定义仪表板中显示文件明智的覆盖率报告。如何获得Xcode服务器代码覆盖率api JSON响应
有没有什么办法可以从这个API(https://developer.apple.com/library/content/documentation/Xcode/Conceptual/XcodeServerAPIReference/CodeCoverage.html)获得JSOn响应而不是.bz2文件?
答
不幸的是,API只返回.bz2压缩的JSON文件。 即使在指定Accept = application/json的HTTP标头时也是如此。
解决此问题的唯一方法是解压缩数据以访问基础JSON。
下面是什么,这可能看起来像在iOS /快捷使用框架BZipCompression解压缩数据流的例子:
import Foundation
import BZipCompression
public class Coverage {
public typealias CoverageCompletion = (_: Data?, _: Error?) -> Void
public enum Errors: Error {
case invalidURL
case invalidResponse
case invalidStatusCode
case invalidData
}
static var session: URLSession {
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: LocalhostSessionDelegate.default, delegateQueue: nil)
return session
}
static public func coverage(forIntegrationWithIdentifier identifier: String, completion: @escaping CoverageCompletion) {
guard let url = URL(string: "https://localhost:20343/api/integrations/\(identifier)/coverage") else {
completion(nil, Errors.invalidURL)
return
}
let request = URLRequest(url: url)
let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil else {
completion(nil, error)
return
}
guard let urlResponse = response as? HTTPURLResponse else {
completion(nil, Errors.invalidResponse)
return
}
guard urlResponse.statusCode == 200 else {
completion(nil, Errors.invalidStatusCode)
return
}
guard let d = data else {
completion(nil, Errors.invalidData)
return
}
var decompressedData: Data
do {
decompressedData = try self.decompress(data: d)
} catch let decompressionError {
completion(nil, decompressionError)
return
}
completion(decompressedData, nil)
}
task.resume()
}
static internal func decompress(data: Data) throws -> Data {
let decompressedData = try BZipCompression.decompressedData(with: data)
guard let decompressedString = String(data: decompressedData, encoding: .utf8) else {
throw Errors.invalidData
}
guard let firstBrace = decompressedString.range(of: "{") else {
throw Errors.invalidData
}
guard let lastBrace = decompressedString.range(of: "}", options: .backwards, range: nil, locale: nil) else {
throw Errors.invalidData
}
let range = decompressedString.index(firstBrace.lowerBound, offsetBy: 0)..<decompressedString.index(lastBrace.lowerBound, offsetBy: 1)
let json = decompressedString.substring(with: range)
guard let validData = json.data(using: .utf8) else {
throw Errors.invalidData
}
return validData
}
}
/// Class implementing the NSURLSessionDelegate which forcefully bypasses untrusted SSL Certificates.
public class LocalhostSessionDelegate: NSObject, URLSessionDelegate {
static public var `default` = LocalhostSessionDelegate()
// MARK: - NSURLSessionDelegate
@objc open func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.previousFailureCount < 1 else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
var credentials: URLCredential?
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if let serverTrust = challenge.protectionSpace.serverTrust {
credentials = URLCredential(trust: serverTrust)
}
}
completionHandler(.useCredential, credentials)
}
}
我注意到,解压缩数据通常包含无效的控制字符和其他垃圾在有效的JSON块的开始和结尾处。解压缩()在完成块中返回之前清理数据。
你可能想看看我在GitHub上的swift XCServerAPI框架。我将添加Code Coverage端点与这个确切的解决方案。
我想要在基于角度/离子的Web应用程序中使用此代码覆盖API以在仪表板中显示它。我需要这个JSON数据,而不是在我的iOS应用程序。我应该在这种情况下做什么?我是否应该要求我的Web开发人员下载此.bz2并将其转换为JSON以显示数据? – yaali
您可以使用类似CompressJS(https://github.com/cscott/compressjs)在JavaScript中执行解压缩。数据解压后,您应该拥有可以与之交互的有效JSON。请记住Code Coverage API将为任何没有数据的集成返回一个404状态码。 – richardpiazza