Как получить версию протокола HTTP из заданного NSHTTPURLResponse?

Из NSHTTPURLResponse документации я не нашел способа получить HTTP версию (i.e. "HTTP/1.1" or "HTTP/1.0").

Поля заголовка HTTP доступны через все свойства полей заголовка, однако версия протокола HTTP не указывается в полях заголовка, поскольку это не заголовок HTTP.

Примечание: init, NSHTTPURLResponse initializer (initWithURL:statusCode:HTTPVersion:headerFields:) требует HTTPVersion в качестве входных данных, поэтому теоретически он мог быть сохранен там.

Однако я не смог найти свойство или метод для получения HTTPVersion из заданного ответа, например, ответа, возвращенного из задачи NSURLSessionDataTask.


person AmitW    schedule 06.09.2016    source источник


Ответы (2)


Не существует общедоступного способа доступа к http-версии экземпляра NSHTTPURLResponse, а версия ответа зависит от версии запроса.

Вы можете использовать CFNetworking, если вы действительно хотите получить доступ к http-версии.

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

И CFHTTPMessageCopyVersion() возвращает версию 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;

Вы можете получить эту структуру, используя метод получения _CFURLResponse для экземпляра NSURLResponse:

CFTypeRef test = CFBridgingRetain([response performSelector:NSSelectorFromString(@"_CFURLResponse")]);
CFShow(test);
person Elf Sundae    schedule 06.09.2016

Пожалуйста, не используйте _CFURLResponse частный API, так как CFNetwork не гарантирует формат возвращаемого значения.

Рекомендуемый способ запроса версии HTTP — реализовать метод делегата URLSession:task:didFinishCollectingMetrics:.

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

person Guoye Zhang    schedule 18.01.2019