static void _network_prepStep_applyAcceptEncodingsToScratchURLRequest()

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);
        }

    }
}