AmitW AmitW - 2 months ago 29
HTTP Question

How to get HTTP protocol version from a given NSHTTPURLResponse?

From

NSHTTPURLResponse
documentation, I did not find a way to get the
HTTP
version
(i.e. "HTTP/1.1" or "HTTP/1.0")
.

HTTP
header fields are available through all Header Fields property, however the
HTTP
protocol version is not given inside the header fields as it is not an
HTTP
header.

Note: init,
NSHTTPURLResponse
initializer
(initWithURL:statusCode:HTTPVersion:headerFields:)
does require the
HTTPVersion
as an input, so theoretically it may have been saved there.

However, I couldn't find a property or method to get the
HTTPVersion
from a given response, for example a response returned from an NSURLSessionDataTask.

Answer

There's no public way to access the http version of an NSHTTPURLResponse instance, and the version of response is depended on the request version.

You can use CFNetworking if you really want to access the http version.

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

And the CFHTTPMessageCopyVersion() returns the HTTP version.

Actually the -[NSHTTPURLResponse initWithURL:(NSURL *)URL statusCode:(NSInteger)statusCode HTTPVersion:(NSString *)version headerFields:(NSDictionary *)fields] uses CFHTTPMessageCreateResponse to create a HTTP response. see NSURLResponse.m

The NSURLResponse is backed upon the _CFURLResponse struct.

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;

You can get this struct using _CFURLResponse getter method on a NSURLResponse instance:

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