in Source/TNLRequestOperation.m [1386:1495]
static void _network_prepStep_applyAcceptEncodingsToScratchURLRequest(TNLRequestOperation * __nullable const self, tnl_request_preparation_block_t nextBlock)
{
if (!self) {
return;
}
TNLAssert(nextBlock != nil);
TNLAssert([self _network_isPreparing]);
tnl_defer(nextBlock);
// Do we do decoding?
switch (self->_requestConfiguration.responseDataConsumptionMode) {
case TNLResponseDataConsumptionModeStoreInMemory:
case TNLResponseDataConsumptionModeChunkToDelegateCallback:
break;
default:
// won't decode
return;
}
switch (self->_requestConfiguration.executionMode) {
case TNLRequestExecutionModeInApp:
case TNLRequestExecutionModeInAppBackgroundTask:
break;
default:
// won't decode
return;
}
// Store the decoders that we'll use
NSArray<id<TNLContentDecoder>> *additionalDecoders = self->_requestConfiguration.additionalContentDecoders;
BOOL didSetAdditionalDecoders = NO;
NSMutableSet<NSString *> *decoderTypes = [NSMutableSet setWithCapacity:additionalDecoders.count + 3];
if ([NSURLSessionConfiguration tnl_URLSessionSupportsDecodingBrotliContentEncoding]) {
[decoderTypes addObject:@"br"]; // supported by default on recent OSes
}
[decoderTypes addObject:@"gzip"]; // supported by default
[decoderTypes addObject:@"deflate"]; // supported by default
if (additionalDecoders.count > 0) {
NSMutableDictionary<NSString *, id<TNLContentDecoder>> *decoders = [[NSMutableDictionary alloc] initWithCapacity:additionalDecoders.count];
for (id<TNLContentDecoder> decoder in additionalDecoders) {
NSString *decoderType = [[decoder tnl_contentEncodingType] lowercaseString];
if (![decoderTypes containsObject:decoderType]) {
[decoderTypes addObject:decoderType];
decoders[decoderType] = decoder;
}
}
if (decoders.count > 0) {
self.additionalDecoders = [decoders copy];
didSetAdditionalDecoders = YES;
} else {
self.additionalDecoders = nil;
}
} else {
self.additionalDecoders = nil;
}
NSString *HTTPHeaderDecoderTypesString = [[self->_scratchURLRequest valueForHTTPHeaderField:@"Accept-Encoding"] lowercaseString];
if (!HTTPHeaderDecoderTypesString) {
// No Accept-Encoding set
if (didSetAdditionalDecoders) {
// Set the Accept-Encoding to our supported decoders
NSArray<NSString *> *sortedDecoderTypes = [decoderTypes.allObjects sortedArrayUsingSelector:@selector(compare:)];
HTTPHeaderDecoderTypesString = [sortedDecoderTypes componentsJoinedByString:@", "];
[self->_scratchURLRequest setValue:HTTPHeaderDecoderTypesString forHTTPHeaderField:@"Accept-Encoding"];
}
}
if (gTwitterNetworkLayerAssertEnabled && didSetAdditionalDecoders) {
// A custom set of Accept-Encodings were provided... let's validate (but not fail)
NSMutableSet<NSString *> *HTTPHeaderDecoderTypesSet = nil;
NSArray<NSString *> *HTTPHeaderDecoderTypes = [HTTPHeaderDecoderTypesString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@", "]];
if (HTTPHeaderDecoderTypes.count) {
HTTPHeaderDecoderTypesSet = [NSMutableSet setWithCapacity:(HTTPHeaderDecoderTypes.count / 2) + 1];
for (NSString *decoderType in HTTPHeaderDecoderTypes) {
NSArray<NSString *> *decoderTypeComponents = [decoderType componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"; "]];
NSString *decoderTypeTrue = decoderTypeComponents.firstObject;
if (decoderTypeTrue.length) {
if ([decoderType isEqualToString:@"*"]) {
// ballsy! will take anything in response
TNLLogWarning(@"%@ has `Accept-Encoding: %@` - this can be overly accepting!", self->_originalRequest, HTTPHeaderDecoderTypesString);
return;
}
[HTTPHeaderDecoderTypesSet addObject:decoderTypeTrue];
}
}
}
NSMutableSet<NSString *> *diff = [HTTPHeaderDecoderTypesSet mutableCopy];
[diff minusSet:decoderTypes];
if (diff.count > 0) {
NSArray<NSString *> *sortedDecoderTypes = [decoderTypes.allObjects sortedArrayUsingSelector:@selector(compare:)];
NSString *decoderTypesString = [sortedDecoderTypes componentsJoinedByString:@", "];
TNLLogWarning(@"%@ has `Accept-Encoding: %@` - but only has specified decoders for `%@`", self->_originalRequest, HTTPHeaderDecoderTypesString, decoderTypesString);
}
}
}