Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[ios] Provide a custom NSURLSessionDelegate? #11888

Closed
halset opened this issue May 11, 2018 · 21 comments
Closed

[ios] Provide a custom NSURLSessionDelegate? #11888

halset opened this issue May 11, 2018 · 21 comments
Labels
gl-ios iOS Mapbox Maps SDK for iOS

Comments

@halset
Copy link
Contributor

halset commented May 11, 2018

I want to use Mapbox GL with a tile server that uses HTTP Basic Authentication. For that, it would be nice to have a way to provide a NSURLSessionDelegate to the NSURLSession used to download tiles.

@friedbunny friedbunny added the iOS Mapbox Maps SDK for iOS label May 11, 2018
@sebastianludwig
Copy link

Related to #12026

@datwelk
Copy link

datwelk commented Jun 6, 2018

Regarding HTTP Basic Auth, Mapbox GL JS has a transformRequest option, see:

mapbox/mapbox-gl-js#5021
mapbox/mapbox-gl-js#5344

As a possible alternative to a custom NSURLSessionDelegate and for feature parity, it would be nice if the iOS implementation also provides the same functionality. We could then use it to set a HTTP Basic Auth header on the tile requests.

@sebastianludwig
Copy link

If I'm not mistaken, the iOS SDK offers that functionality as part of the MGLOfflineStorageDelegate.

@halset
Copy link
Contributor Author

halset commented Jun 7, 2018

@sebastianludwig it return a NSURL. As far as I know, you can not use that to take a HTTP Basic Authentication challenge, ask the user for a username/password and then encode that in the new request.

@sebastianludwig
Copy link

Aaah, true - never mind 👍

@1ec5
Copy link
Contributor

1ec5 commented Jun 21, 2018

We discussed doing something similar to transformRequest based on NSURLProtocol at one point in #7485, but we wound up implementing only a way to transform the URL. I think the primary consideration at the time was cross-platform compatibility, but mapbox/mapbox-gl-js#5021 and #10948 undermine that argument.

A way to provide either an NSURLSessionDelegate or an NSURLProtocol would be nice indeed, especially for folks who need to customize caching behavior.

/cc @kkaefer @julianrex

@kkaefer
Copy link
Member

kkaefer commented Jun 25, 2018

A way to provide either an NSURLSessionDelegate or an NSURLProtocol would be nice indeed, especially for folks who need to customize caching behavior.

Mapbox GL does its own caching and doesn't rely on Cocoa's built-in caching. We do this because we need to tightly control resource expiration and ensure that they don't get evicted for offline packs.

@datwelk
Copy link

datwelk commented Sep 11, 2018

A way to provide either an NSURLSessionDelegate or an NSURLProtocol would be nice indeed, especially for folks who need to customize caching behavior.

How could we move this functionality forward? It's crucial for us to adopt Mapbox GL. I'd be happy to help out if needed. @1ec5 @kkaefer

@lilykaiser
Copy link

Hi @datwelk , we do not have plans to implement this in the foreseeable future because of competing priorities that we think bring value to more Mapbox developers. We consider https://mapbox.github.io/top-issues/#!mapbox/mapbox-gl-native when setting our priorities. This page takes user reactions into account, so if you’d like to raise this issue on our priority list, please vote for it using the 👍 reaction. A next step for implementing this issue would be to lay out your design ideas here so we can make sure they’re compatible with the rest of our SDK design.

@datwelk
Copy link

datwelk commented Sep 12, 2018

Hi @lilykaiser, thanks for your reply. The top issue on that page is from October 31 2016, with most recent activity on February 12th 2018. Hence I can only conclude that there seems to be quite some time passing by without the top issue resolved - could you clarify how indicative of internal priorities this top issues list is?

@lilykaiser
Copy link

Hi @datwelk , the top issues list is a big part of how we gauge user interest on GitHub, it’s just that user interest is not the only factor that guides our choices. We also take into account the size of the project, feedback from internal teams, and strategic goals. We don’t get to work on as many top issues as we like, but we do consider how much users need them and try to work them into our roadmap.

@sebastianludwig
Copy link

I'd be happy to implement the feature, all I need is a guiding strategy how to go about it. I know, that's still a lot to ask, especially taking the time for the PR feedback into account too. But still, please let me know if that changes anything for you.

@datwelk
Copy link

datwelk commented Sep 25, 2018

FWIW, for now we have worked around the limitation of not being able to set custom HTTP headers by implementing a local proxy server running on the iOS device. Tile requests specify headers encoded as a URL param to localhost, localhost transforms this param into HTTP headers and relays the request + response.

@halset
Copy link
Contributor Author

halset commented Dec 1, 2018

Take a look at #13491 for one possible solution to this issue.

@JesseCrocker
Copy link
Contributor

I've accomplished adding headers by swizzling NSURLSessionConfiguration defaultSessionConfiguration and returning a config that is not the default if it was requested by mapbox-gl.

@halset
Copy link
Contributor Author

halset commented Dec 5, 2018

@JesseCrocker How did you do that? And it is cleaner than #13491?

@JesseCrocker
Copy link
Contributor

JesseCrocker commented Dec 5, 2018

I dont know if swizzling is cleaner, but it will let you stay on a current release rather than having to use a custom build.

#import "NSURLSessionConfiguration+Referer.h"
#import <objc/runtime.h>
#import "NSObject+DTRuntime.h"


@implementation NSURLSessionConfiguration (Referer)


+ (void)load {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
      [[self class] swizzleClassMethod:@selector(defaultSessionConfiguration) withMethod:@selector(__swizzle_defaultSessionConfiguration)];
    
  });
}


+(NSURLSessionConfiguration*) __swizzle_defaultSessionConfiguration {
  NSURLSessionConfiguration * sessionConfig = [NSURLSessionConfiguration __swizzle_defaultSessionConfiguration];
  
  NSArray<NSString*>* stack = [NSThread callStackSymbols];
  if ([stack count] > 1 && [stack[1] containsString:@"Mapbox"]) {
    NSMutableDictionary * headerDict = [[NSMutableDictionary alloc] initWithDictionary:sessionConfig.HTTPAdditionalHeaders];
    headerDict[@"referer"] = @"XXXXX";
    sessionConfig.HTTPAdditionalHeaders = headerDict;
  }
  
  return sessionConfig;
}


@end

NSObject+DTRuntime is from https://github.com/Cocoanetics/DTFoundation/blob/develop/Core/Source/Runtime/NSObject%2BDTRuntime.m

@halset
Copy link
Contributor Author

halset commented Dec 5, 2018

Thanks! I will continue to use #13491 for authentication.

@stale stale bot added the archived Archived because of inactivity label Jun 3, 2019
@stale
Copy link

stale bot commented Jun 3, 2019

This issue has been automatically detected as stale because it has not had recent activity and will be archived. Thank you for your contributions.

@stale stale bot closed this as completed Jun 3, 2019
@chloekraw chloekraw removed the archived Archived because of inactivity label Jul 16, 2019
@chloekraw chloekraw reopened this Jul 16, 2019
@patrickkempff
Copy link

Any news on this?

@JanDriesen
Copy link

Any news on this?

I have solved the issue with @JesseCrocker's attempt. Create an Extension for NSURLSessionConfiguration and add DTFoundation as Pod.

//
//  NSURLSessionConfiguration+Authorization.m
//  CartoDemo
//
//  Created by Jan Driesen on 03.08.20.
//  Copyright © 2020 Driesengard. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "NSURLSessionConfiguration+Authorization.h"
#import <objc/runtime.h>
#import "NSObject+DTRuntime.h"


@implementation NSURLSessionConfiguration (Authorization)

// "register the swizzle" at load
+ (void) load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [[self class] swizzleClassMethod:@selector(defaultSessionConfiguration) withMethod:@selector(__swizzle_defaultSessionConfiguration)];
    });
}

// Overrides the [NSURLSessionConfiguratuion defaultSessionConfiguration] method at runtime!
// this method gets used and adds an Authorization HTTP header field to the Requests made by Mapbox
+ (NSURLSessionConfiguration*) __swizzle_defaultSessionConfiguration
{
    NSURLSessionConfiguration * sessionConfig = [NSURLSessionConfiguration __swizzle_defaultSessionConfiguration];
    
    NSArray<NSString*>* stack = [NSThread callStackSymbols];
    if ([stack count] > 1 && [stack[1] containsString:@"Mapbox"]) {
        // here we add our authentification to get the correct responses from the server
        // TODO: replace the hardcoded values -> get the values from the bridging headers
        NSMutableDictionary * headerDict = [[NSMutableDictionary alloc] initWithDictionary:sessionConfig.HTTPAdditionalHeaders];
        headerDict[@"Authorization"] = [NSURLSessionConfiguration makeBase64AuthorizationForUser: @"username" password:@"somepassword"];
        sessionConfig.HTTPAdditionalHeaders = headerDict;
    }
    
    return sessionConfig;
}

// returns an HTTP Basic Authentification String for the user and password
+ (NSString *) makeBase64AuthorizationForUser:(NSString *)user password:(NSString *)pass
{
    NSString *authString = [NSString stringWithFormat:@"%@:%@", user, pass];
    NSString *auth64String = [[authString dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
    return [NSString stringWithFormat:@"Basic %@", auth64String];
}

@end

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
gl-ios iOS Mapbox Maps SDK for iOS
Projects
None yet
Development

No branches or pull requests