1

这是我在将 iOS 11 (15A5304i) 和 Xcode 9 (9M137d) 更新到最新测试版后开始遇到的问题。

当我恢复到以前的测试版时,它就消失了。

对网站进行任何 GET https 调用都会导致来自服务器的 400 响应。

networkError(FoodAPI.NetworkError.responseStatusError(status: 400, message: "<NSHTTPURLResponse: 0x1c4239700> { URL: https://stackoverflow.com/ } { status code: 400, headers {\n    Date = \"Thu, 22 Jun 2017 17:41:03 GMT\";\n} }"))

这就是我打电话的方式

func callTask(_ request: URLRequest, completion: @escaping (ResultType<Data, NetworkError>) -> Void) {
  let task = URLSession.shared.dataTask(with: request) { data, response, error in

    guard let response = response as? HTTPURLResponse else {
      completion(.failure(.responseInvalidFormat))
      return
    }

    if response.statusCode >= 400 {
      let error = response.description
      completion(.failure(.responseStatusError(status: response.statusCode, message: error)))
      return
    }

    guard let data = data else {
      completion(.failure(.responseNoDataError))
      return
    }

    completion(.success(data))
  }
  task.resume()
}

这就是生成请求的方式:

  private func generateRequest(urlString: String,
                               method: HttpMethod = .get,
                               contentType: ContentType = .json,
                               headers: [String: String] = ["":""],
                               body: [String: Any]? = nil) throws -> URLRequest {


    guard let url = URL(string: urlString) else {
      throw NetworkError.requestGenerationFail(url: urlString, httpMethod: method)
    }
    var request = URLRequest(url: url)
    request.httpMethod = method.rawValue
    request.setValue("***** by Reza: info: reza@example.com", forHTTPHeaderField: "User-Agent")

    request.allHTTPHeaderFields = headers
    if contentType == .urlEncoded && headers["content-type"] ?? "" != ContentType.urlEncoded.rawValue {
      request.addValue(ContentType.urlEncoded.rawValue, forHTTPHeaderField: "content-type")
    }

    if let body = body {
      request.httpBody = try self.generateBody(body: body, contentType: contentType)
    }

    return request
  }

同样,这在以前的 iOS 11 测试版上运行良好,但是新版本会在对 Web 服务器的 https 调用上产生 400 响应,几乎没有数据。

值得注意的是,我首先调用了托管在https://api.yelp.com/上的 Yelp 端点 API 。此连接成功,没有任何问题。对其他主机( https://stackoverflow.com、https : //www.yelp.com )的任何进一步调用都会返回 400。

当我使用旧测试版在模拟器中运行代码时,它工作正常,当我部署到使用新 iOS 的 iPhone 6 时,它会从服务器产生 400。

我没有针对我拥有的服务器对此进行测试,因此我可以查看日志,但是在此过程中出现了一些问题,导致服务器以错误的请求响应返回。这些相同的调用使用 curl、postman、浏览器和以前的 iOS 版本可以正常工作。

我希望遇到同样问题的人能有所启发。

4

1 回答 1

2

我已经确定了问题。虽然原因仍然难以捉摸。

generateRequest函数中,我传递了一个带有请求标头[String:String]默认值的字典。["":""]

看来这request.allHTTPHeaderFields = ["":""]会破坏您的要求。

在以前的版本中,这不会导致任何问题,但这会导致对当前测试版的错误请求。

更新

当我第一次遇到这个问题时,我向 Apple 填写了一个错误,这是他们的回应:

问题是在 CFNetwork-856.4.7(种子 1 的一部分)中,我们犯了一个错误并删除了空白的标头。在种子 2 (CFNetwork-861.1) 中,我们将要删除的标头限制为 4 个“特殊”标头(Content-Type、User-Agent、Accept-Language、Accept-Encoding)。所以,这就是你看到行为变化的原因。

macOS El Capitan 还发送导致 400 HTTP 状态代码的“=”标头。所以,现在种子 2 中的行为是正确的。种子 1 是异常的并且是错误的。

请通过更新您的错误报告让我们知道问题是否已为您解决。

于 2017-06-24T05:53:49.750 回答