如何获取 Xcode 服务器代码覆盖率 API JSON 响应
Posted
技术标签:
【中文标题】如何获取 Xcode 服务器代码覆盖率 API JSON 响应【英文标题】:How to get Xcode server Code coverage api JSON response 【发布时间】:2017-07-19 09:20:07 【问题描述】:当我尝试通过传递集成 ID 来访问 Xcode 服务器代码覆盖 API 时,它不是 JSON 响应,而是直接下载一个 .bz2 文件。我想使用此 API 在我的自定义仪表板中显示文件明智的覆盖率报告。
有什么方法可以让我从这个 API (https://developer.apple.com/library/content/documentation/Xcode/Conceptual/XcodeServerAPIReference/CodeCoverage.html) 而不是 .bz2 文件获得 JSOn 响应?
【问题讨论】:
【参考方案1】:不幸的是,API 只返回 .bz2 压缩的 JSON 文件。 即使指定 Accept=application/json 的 HTTP 标头。
解决此问题的唯一方法是解压缩数据以访问底层 JSON。
以下是使用框架BZipCompression 解压缩数据流的 ios/swift 上的示例:
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 块的开头和结尾处包含无效的控制字符和其他垃圾。 decompress() 在完成块中返回之前清理数据。
您可能想查看我在 GitHub 上的 swift XCServerAPI 框架。我将使用这个确切的解决方案添加代码覆盖率端点。
【讨论】:
我正在尝试在基于角度/离子的 Web 应用程序中使用此代码覆盖率 API 以将其显示在仪表板中。我需要这个 JSON 数据,而不是在我的 iOS 应用程序中。在这种情况下我应该怎么做?我是否应该让我的网络开发人员下载这个 .bz2 并将其转换为 JSON 以显示数据? 您可以使用 CompressJS (github.com/cscott/compressjs) 之类的东西在 javascript 中进行解压缩。解压缩数据后,您应该拥有可以与之交互的有效 JSON。请记住,代码覆盖率 API 将为任何没有数据的集成返回 404 状态代码。以上是关于如何获取 Xcode 服务器代码覆盖率 API JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章