如何从给定的 NSHTTPURLResponse 获取 HTTP 协议版本?

How to get HTTP protocol version from a given NSHTTPURLResponse?

NSHTTPURLResponse 文档中,我没有找到获取 HTTP 版本 (i.e. "HTTP/1.1" or "HTTP/1.0") 的方法。

HTTP header 字段可用于所有 Header 字段 属性,但是 HTTP 协议版本未在 [=30= 中给出] 字段,因为它不是 HTTP header。

注:初始化,NSHTTPURLResponse初始化器 (initWithURL:statusCode:HTTPVersion:headerFields:) 确实需要 HTTPVersion 作为输入,所以理论上它可能已经保存在那里。

但是,我找不到 属性 或方法来从给定的响应中获取 HTTPVersion,例如从 NSURLSessionDataTask 返回的响应。

没有public方式访问NSHTTPURLResponse实例的http版本,响应版本取决于请求版本。

如果你真的想访问http版本,你可以使用CFNetworking

CFN_EXPORT CFHTTPMessageRef 
CFHTTPMessageCreateResponse(
  CFAllocatorRef  __nullable alloc,
  CFIndex         statusCode,
  CFStringRef     __nullable statusDescription,
  CFStringRef     httpVersion)              CF_AVAILABLE(10_1, 2_0);

以及 CFHTTPMessageCopyVersion() returns HTTP 版本。

实际上 -[NSHTTPURLResponse initWithURL:(NSURL *)URL statusCode:(NSInteger)statusCode HTTPVersion:(NSString *)version headerFields:(NSDictionary *)fields] 使用 CFHTTPMessageCreateResponse 创建 HTTP 响应。见 NSURLResponse.m

NSURLResponse 支持 _CFURLResponse 结构。

typedef struct _CFURLResponse {
    CFRuntimeBase _base;
    CFAbsoluteTime creationTime;
    CFURLRef url;
    CFStringRef mimeType;
    int64_t expectedLength;
    CFStringRef textEncoding;
    CFIndex statusCode;
    CFStringRef httpVersion;
    CFDictionaryRef headerFields;
    Boolean isHTTPResponse;

    OSSpinLock parsedHeadersLock;
    ParsedHeaders* parsedHeaders;
} _CFURLResponse;

typedef const struct _CFURLResponse* CFURLResponseRef;

您可以在 NSURLResponse 实例上使用 _CFURLResponse getter 方法获取此结构:

CFTypeRef test = CFBridgingRetain([response performSelector:NSSelectorFromString(@"_CFURLResponse")]);
CFShow(test);

请不要使用 _CFURLResponse private API,因为 CFNetwork 不对其 return 值的格式提供任何保证。

查询HTTP版本的推荐方式是实现URLSession:task:didFinishCollectingMetrics:委托方法

https://developer.apple.com/documentation/foundation/nsurlsessiontasktransactionmetrics/1643141-networkprotocolname?language=objc