GTMSessionFetcher

repository·main·Indexed 43 days ago

https://github.com/google/gtm-session-fetcher

A Cocoa-based library that wraps NSURLSession to provide a simplified, asynchronous interface for HTTP operations. It supports upload and download sessions, automatic retries with exponential backoff, multipart MIME upload streams, plug-in authentication, and per-host rate limiting via the GTMSessionFetcherService factory class.

Tokens
2.3K
Snippets
9
Records
14
Agent score
55%

What's inside GTMSessionFetcher

  1. Overview of GTMSessionFetcher

    main

    GTMSessionFetcher is a library designed for Cocoa applications to simplify HTTP operations. It acts as a wrapper around NSURLSession, providing asynchronous behavior that adheres to operating-system settings.

    Key capabilities include:

    • Session Management: Supports both upload and download sessions.
    • Resilience: Automatic retry on errors using exponential backoff.
    • Data Handling: Support for generating multipart MIME upload streams.
    • Authentication: Supports plug-in authentication (e.g., GTMAppAuth).
    • Cookie Management: Flexible cookie storage options.
    • Observability: Convenient logging of HTTP requests and responses.
    • Rate Limiting: Automatic rate limiting when instantiated via the GTMSessionFetcherService factory class.
    • Testability: Designed to be easily testable via self-mocking.
  2. Create a GitHub release

    main

    After updating the version in the repository, create a new release on GitHub:

    1. Navigate to the project's release page.
    2. Select Draft a new release.
    3. Use a tag in the format vX.Y.Z (e.g., v1.3.1). Note: The tag must exactly match the version number used in the update_version.py script, including the v prefix.
    4. Use the Generate release notes button to populate the description, then refine it to highlight major changes and remove CI-related noise.
  3. Enable and Locate HTTP Logging

    main

    To generate log files for debugging HTTP traffic, call [GTMSessionFetcher setLoggingEnabled:YES]. Note that on iOS, logging is stripped in non-DEBUG builds unless DEBUG=1 or STRIP_GTM_FETCH_LOGGING=0 is defined.

    Log Locations:

    • macOS: A folder named GTMHTTPDebugLogs on the desktop.
    • iOS Simulator: The project's derived data directory in ~/Library/Application Support.
    • iOS Device: The application's documents directory.

    Tip: Search the Xcode console for GTMSessionFetcher logging to to find the exact path. You can open the path in Terminal using open "<path>".

    [GTMSessionFetcher setLoggingEnabled:YES];
  4. Import GTMSessionFetcher in Objective-C

    main

    Because CocoaPods and SwiftPM use different module models, use framework imports to ensure compatibility across both packaging systems. All packages export headers as GTMSessionFetcher/HEADER.h.

    #import <GTMSessionFetcher/GTMSessionFetcher.h>
    #import <GTMSessionFetcher/GTMSessionFetcherService.h>
  5. Install GTMSessionFetcher via CocoaPods

    main

    To integrate the library using CocoaPods, add the GTMSessionFetcher pod to your Podfile.

    There are three available subspecs:

    • GTMSessionFetcher/Core: Minimum parts of the library.
    • GTMSessionFetcher/Full: Includes multipart MIME uploads/downloads and resumable uploads.
    • GTMSessionFetcher/LogView: Provides an iOS view for browsing HTTP logs.

    Note: CocoaPods is being phased out; it is recommended to migrate to Swift Package Manager.

    pod 'GTMSessionFetcher/Full'
  6. Install GTMSessionFetcher via Swift Package Manager (SwiftPM)

    main

    Add the library via Xcode's UI or a Package.swift file. Choose the product that matches your requirements:

    • GTMSessionFetcherCore: Minimum parts of the library.
    • GTMSessionFetcherFull: Includes multipart MIME uploads/downloads and resumable uploads.
    • GTMSessionFetcherLogView: Provides an iOS view for browsing HTTP logs.
  7. Set up the development environment in Xcode

    main

    To develop or test the project locally, open the Package.swift file using Xcode.

    • Use the GTMSessionFetcher-Package scheme to build the entire project and run tests.
    • Select your desired target platform by choosing the appropriate run destination alongside the scheme.
    # Open the project in Xcode
    open Package.swift
  8. Publish the CocoaPod

    main

    To publish the updated version to CocoaPods, use the pod trunk push command.

    Important: Use the --skip-tests flag. CocoaPods currently encounters issues when testing specs that include a watchOS target. Since CI provides testing coverage for PRs, skipping tests during the push is the standard procedure.

    pod trunk push --skip-tests GTMSessionFetcher.podspec
  9. Fetch a URL using GTMSessionFetcher

    main

    The fetcher is an asynchronous wrapper around NSURLSession. It is recommended to use a GTMSessionFetcherService to create fetcher instances. Each fetcher object is intended for "one shot" usage; do not reuse an instance for multiple fetches. The callback executes on the callback queue (defaulting to the main queue).

    #import <GTMSessionFetcher/GTMSessionFetcher.h>
    #import <GTMSessionFetcher/GTMSessionFetcherService.h>
    
    _fetcherService = [[GTMSessionFetcherService alloc] init];
    
    GTMSessionFetcher *myFetcher = [_fetcherService fetcherWithURLString:myURLString];
    myFetcher.retryEnabled = YES;
    myFetcher.comment = @"First profile image";
    
    // Optionally specify a file URL or NSData for the request body to upload.
    myFetcher.bodyData = [postString dataUsingEncoding:NSUTF8StringEncoding];
    
    [myFetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error) {
      if (error != nil) {
        // Server status code or network error.
        // If the domain is kGTMSessionFetcherStatusDomain then the error code
        // is a failure status from the server.
      } else {
        // Fetch succeeded.
      }
    }];
  10. Configure Automatic Retry with Exponential Backoff

    main

    The fetcher can automatically retry specific failures (e.g., 408, 502, 503, 504, or network timeouts) using exponential backoff.

    Key properties:

    • retryEnabled: Set to YES to enable retries.
    • maxRetryInterval: Sets the maximum interval between retries (default is 60s for downloads, 600s for uploads).
    • retryBlock: A callback block to customize which errors trigger a retry.

    When retries are enabled, the success/failure callbacks are only invoked after all retry attempts are exhausted. Calling stopFetching on the fetcher will terminate the retry timer immediately without invoking the completion handler.

    myFetcher.retryEnabled = YES;
    
    myFetcher.maxRetryInterval = 60.0; // in seconds
    
    myFetcher.retryBlock = ^(BOOL suggestedWillRetry, NSError *error, 
                             GTMSessionFetcherRetryResponse response) {
      // Respond with YES to start the retry timer, NO to proceed to the failure callback,
      // or suggestedWillRetry to get default behavior.
      response(suggestedWillRetry);
    };
  11. Handle Proxy Authentication Challenges

    main

    If a proxy authentication error occurs, the fetcher invokes the completion callback with an NSURLChallenge inside the error's userInfo. You can extract the challenge using the kGTMSessionFetcherErrorChallengeKey to identify if it is a proxy challenge and then provide credentials using setProxyCredential: on the next fetcher attempt.

    NSURLAuthenticationChallenge *challenge = [error.userInfo objectForKey:kGTMSessionFetcherErrorChallengeKey];
    BOOL isProxyChallenge = challenge.protectionSpace.isProxy;