防止NSURLSession使用默认的HTTP标头

5
我正在尝试构建一个非常具体的HTTP请求,向服务器发送(即定义确切的HTTP标头集),但是NSURLSession会“有用地”插入一堆HTTP标头,如Accept、Accept-Language和Accept-Encoding。
考虑下面这个Playground(Swift 2.x)发送一个请求到一个服务,该服务只回显发送的HTTP标头:
import Foundation
import XCPlayground

XCPlaygroundPage.currentPage.needsIndefiniteExecution = true

let url = NSURL(string: "http://httpbin.org/headers")!
let request = NSMutableURLRequest(URL: url, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 30000)
let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
let session = NSURLSession(configuration: configuration)

let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) in
    print(NSString(data: data!, encoding: NSUTF8StringEncoding))
    XCPlaygroundPage.currentPage.finishExecution()
}
task.resume()

您可以看到有三个“Accept”头被发送了。我该如何防止这种情况发生?
我尝试使用“request.setValue(nil, forHTTPHeaderField:“Accept-Language”)”来设置标头,但这被忽略了。尝试将其设置为“”,但没有效果。我还尝试操作NSURLSessionConfiguration上的HTTPAdditionalHeaders属性,但也没有用。
我该如何让NSURLSession不那么“热心助人”?
1个回答

4
我怀疑您所要求的是不可能实现的。NSURLSession(和NSURLConnection)自动提供了许多标头,其中就包括这个。
此外,没有有效的理由删除它们。这三个标头都是自原始HTTP/0.9规范以来的一部分(https://www.w3.org/Protocols/HTTP/HTRQ_Headers.html)。任何服务器都没有任何借口不正确处理或直接忽略它们。
话虽如此,如果您为这些字段提供了错误的值(默认值可能是错误的),则服务器可能会拒绝向您提供结果。为解决这个问题,首先要确定服务器实际上将提供什么类型的数据,并在Accept标头中指定该值,而不是使用默认值。
例如,如果您期望JSON数据,则可以将Accept设置为“application/json”或其他变体(What is the correct JSON content type?)。
如果你真的必须避免发送这些标头,你可以打开套接字,手动构造请求并发送。假设服务器不需要分块编码,那么这很容易实现。(然而,分块编码是一个巨大的问题,如果你的服务器返回这个,你就必须添加libcurl到你的项目中,并使用它来代替发送请求。)

谢谢您的想法。我的情况有点特殊,因为我的应用程序(serveupapp.com)是接受来自远程源(可能是正在开发中的移动应用程序)的传入请求,并返回模拟响应或将其转发到真实服务器的应用程序。我真的希望忠实地转发我收到的确切标头集...正如您所说,几乎可以肯定我实际上会收到这些标头,但我只是在考虑我将如何处理我没有的情况。 - Craig Edwards
看了一下Swift的开源代码(https://github.com/apple/swift-corelibs-foundation/blob/db54d310bf348de6834d1ec9f83721d403100ccf/Foundation/NSURLSession/NSURLSessionTask.swift#L594),似乎所有东西都被委托给了libcurl。不幸的是,`NSURLSession`及其相关类的结构似乎使得覆盖这些方法有点棘手,需要使用一些易碎的魔法,而这些魔法可能会在不同版本之间发生变化。我可能只能接受它。 - Craig Edwards
你在那里看到的并不是实际的Foundation网络源代码。这只是苹果提供的一个兼容层,以便在非Mac平台上使用NSURLSession的最关键部分。因此,很多东西都完全缺失了,例如后台会话。真正的NSURLSession实现是用Objective-C编写的,并且据我所知,在CFNetwork之上是一个相当薄的层,而CFNetwork是用C/C++编写的。当然,除非你正在Linux或其他操作系统上使用此API。 - dgatwood
抱歉回复晚了。我最终向苹果提出了支持请求以了解他们的建议。简而言之,NSURLSession 基本上依赖于一些设置的头文件(它实际上发送了一些技术上不需要的头文件)。无论如何,如果我不想要这种行为,我需要降低级别。NSURLConnection 不好用,因为它在底层使用 NSURLSessionCFHTTPStream 可能是最好的选择,我可以使用 CFHTTPMessage 进行 HTTP 解析。或者,我可以查看其他第三方库。感谢您的帮助和建议。 - Craig Edwards

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接