static void _network_prepStep_applyContentEncodingToScratchURLRequest()

in Source/TNLRequestOperation.m [1497:1569]


static void _network_prepStep_applyContentEncodingToScratchURLRequest(TNLRequestOperation * __nullable const self, tnl_request_preparation_block_t nextBlock)
{
    if (!self) {
        return;
    }

    TNLAssert(nextBlock != nil);
    TNLAssert([self _network_isPreparing]);

    // Body to encode?
    NSData *body = self->_scratchURLRequest.HTTPBody;
    if (!body.length) {
        nextBlock();
        return;
    }

    // Encoder to encode with?
    id<TNLContentEncoder> encoder = self->_requestConfiguration.contentEncoder;
    if (!encoder) {
        nextBlock();
        return;
    }

    // If there's a preset "Content-Encoding", can we handle it?
    NSString *encoderType = [[encoder tnl_contentEncodingType] lowercaseString];
    NSString *HTTPHeaderEncoderType = [[self->_scratchURLRequest valueForHTTPHeaderField:@"Content-Encoding"] lowercaseString];
    if (HTTPHeaderEncoderType && ![HTTPHeaderEncoderType isEqualToString:encoderType]) {
        [self _network_fail:TNLErrorCreateWithCode(TNLErrorCodeRequestOperationRequestContentEncodingTypeMissMatch)];
        return;
    }

    // Jump to coding queue
    tnl_dispatch_async_autoreleasing(tnl_coding_queue(), ^{

        // Do encoding
        const uint64_t startMachTime = mach_absolute_time();
        NSError *encoderError;
        NSData *encodedData = [encoder tnl_encodeHTTPBody:body error:&encoderError];
        const NSTimeInterval encodeLatency = TNLComputeDuration(startMachTime, mach_absolute_time());
        const BOOL skipEncoding = (encoderError.code == TNLContentEncodingErrorCodeSkipEncoding) &&
                                  [encoderError.domain isEqualToString:TNLContentEncodingErrorDomain];

        // Back to network queue
        tnl_dispatch_async_autoreleasing(tnl_network_queue(), ^{

            // Error?
            if (!encodedData && !skipEncoding) {
                [self _network_fail:TNLErrorCreateWithCodeAndUnderlyingError(TNLErrorCodeRequestOperationRequestContentEncodingFailed, encoderError)];
                return;
            }

            // Success!
            if (skipEncoding) {
                self->_scratchURLRequest.HTTPBody = body;
                [self->_scratchURLRequest setValue:nil forHTTPHeaderField:@"Content-Encoding"];
            } else {
                const NSUInteger originalLength = body.length;
                const NSUInteger encodedLength = encodedData.length;
                self->_scratchURLRequest.HTTPBody = encodedData;
                [self->_scratchURLRequest setValue:encoderType forHTTPHeaderField:@"Content-Encoding"];
                self->_scratchURLRequestEncodeLatency = encodeLatency;
                self->_scratchURLRequestOriginalBodyLength = (SInt64)originalLength;
                self->_scratchURLRequestEncodedBodyLength = (SInt64)encodedLength;
#if DEBUG
                const double ratio = (encodedLength) ? (double)originalLength / (double)encodedLength : 0;
                TNLLogDebug(@"%@ compression ratio: %f", self->_scratchURLRequest.URL, ratio);
#endif
            }

            nextBlock();
        });
    });
}