状态代码 400:使用 URLSession.shared.dataTask 进行的调用的 NSHTTPURLResponse
Status code 400: NSHTTPURLResponse on calls made using URLSession.shared.dataTask
这是我在将 iOS 11 (15A5304i) 和 Xcode 9 (9M137d) 更新到最新测试版后开始遇到的问题。
当我恢复到之前的测试版时,它就消失了。
对网站进行任何 GET https 调用都会导致服务器返回 400 响应。
networkError(FoodAPI.NetworkError.responseStatusError(status: 400, message: "<NSHTTPURLResponse: 0x1c4239700> { URL: https://whosebug.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/. This connection succeeded without any issue. Any further calls to other host (https://whosebug.com, https://www.yelp.com 上的 Yelp 的端点 API)返回 400。
当我 运行 模拟器中的代码使用旧测试版时,它工作正常,当我部署到使用新 iOS 的 iPhone 6 时,结果是 400服务器。
我还没有在我拥有的服务器上测试过这个,所以我可以查看日志,但是过程中出现了一些问题,导致服务器以错误的请求响应卷土重来。这些相同的调用在使用 curl、postman、浏览器和以前的 iOS 版本时工作正常。
我希望遇到同样问题的人能给出一些启示。
我已经查明问题所在。虽然原因仍然难以捉摸。
在 generateRequest
函数中,我为请求 header 传递了具有默认值 ["":""]
的 [String:String]
字典。
看来 request.allHTTPHeaderFields = ["":""]
会破坏您的请求。
在以前的版本中,这不会导致任何问题,但这会导致当前测试版出现错误请求。
更新
当我第一次遇到这个问题时,我向 Apple 提交了一个错误,这是他们的回应:
问题是在 CFNetwork-856.4.7(种子 1 的一部分)中我们犯了一个错误,删除了空白的 header。在种子 2(CFNetwork-861.1)中,我们将要删除的 headers 限制为 4 个“特殊”headers(Content-Type、User-Agent、Accept-Language , Accept-Encoding).所以,这就是您看到行为发生变化的原因。
macOS El Capitan 还发送“=”header 导致 400 HTTP 状态代码。所以,这在种子 2 中现在表现正确。种子 1 是一个异常并且是错误的。
请让我们知道问题是否已通过更新错误报告为您解决。
这是我在将 iOS 11 (15A5304i) 和 Xcode 9 (9M137d) 更新到最新测试版后开始遇到的问题。
当我恢复到之前的测试版时,它就消失了。
对网站进行任何 GET https 调用都会导致服务器返回 400 响应。
networkError(FoodAPI.NetworkError.responseStatusError(status: 400, message: "<NSHTTPURLResponse: 0x1c4239700> { URL: https://whosebug.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/. This connection succeeded without any issue. Any further calls to other host (https://whosebug.com, https://www.yelp.com 上的 Yelp 的端点 API)返回 400。
当我 运行 模拟器中的代码使用旧测试版时,它工作正常,当我部署到使用新 iOS 的 iPhone 6 时,结果是 400服务器。
我还没有在我拥有的服务器上测试过这个,所以我可以查看日志,但是过程中出现了一些问题,导致服务器以错误的请求响应卷土重来。这些相同的调用在使用 curl、postman、浏览器和以前的 iOS 版本时工作正常。
我希望遇到同样问题的人能给出一些启示。
我已经查明问题所在。虽然原因仍然难以捉摸。
在 generateRequest
函数中,我为请求 header 传递了具有默认值 ["":""]
的 [String:String]
字典。
看来 request.allHTTPHeaderFields = ["":""]
会破坏您的请求。
在以前的版本中,这不会导致任何问题,但这会导致当前测试版出现错误请求。
更新
当我第一次遇到这个问题时,我向 Apple 提交了一个错误,这是他们的回应:
问题是在 CFNetwork-856.4.7(种子 1 的一部分)中我们犯了一个错误,删除了空白的 header。在种子 2(CFNetwork-861.1)中,我们将要删除的 headers 限制为 4 个“特殊”headers(Content-Type、User-Agent、Accept-Language , Accept-Encoding).所以,这就是您看到行为发生变化的原因。
macOS El Capitan 还发送“=”header 导致 400 HTTP 状态代码。所以,这在种子 2 中现在表现正确。种子 1 是一个异常并且是错误的。
请让我们知道问题是否已通过更新错误报告为您解决。