NSURLSessionTaskMetrics with custom NSURLProtocol

Hi,


I would like to create a custom network library by implementing and regestering a custom NSURLProtocol. The library should be able to populate NSURLSessionTaskMetrics and return it to the client using the standard URLSession:task:didFinishCollectingMetrics: callback method of the NSURLSessionTaskDelegate class. I would expect NSURLProtocolClient to have a method that would allow passing the metrics to the client; however I wasn't able to find one. What would be the best approach to implement that kind of functionallity?


Thank you!

Accepted Reply

I would expect NSURLProtocolClient to have a method that would allow passing the metrics to the client

Indeed.

however I wasn't able to find one.

That’s correct.

What would be the best approach to implement that kind of functionallity?

I don’t think you’ll be able to do this. CFNetwork’s support for custom protocols (that is, subclasses of

NSURLProtocol
) is rather lacking. It’s not completely useless — there are scenarios where a custom protocol is the best way to get something done — but there’s no way that you can make a custom protocol that does all the stuff that the built-in HTTP[S] protocol does.

You should feel free to file an enhancement request for the features you need, making sure to describe your use case. However, I have to set expectations here.

NSURLProtocolClient
has not been updated to account for features that we added in Mac OS X 10.6 (!) [1], so it’s clearly not a high priority.

If you do file an ER, please post your bug number here, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Namely, an entry point that that’s equivalent to the

-connection:canAuthenticateAgainstProtectionSpace:
delegate callback.

Replies

I would expect NSURLProtocolClient to have a method that would allow passing the metrics to the client

Indeed.

however I wasn't able to find one.

That’s correct.

What would be the best approach to implement that kind of functionallity?

I don’t think you’ll be able to do this. CFNetwork’s support for custom protocols (that is, subclasses of

NSURLProtocol
) is rather lacking. It’s not completely useless — there are scenarios where a custom protocol is the best way to get something done — but there’s no way that you can make a custom protocol that does all the stuff that the built-in HTTP[S] protocol does.

You should feel free to file an enhancement request for the features you need, making sure to describe your use case. However, I have to set expectations here.

NSURLProtocolClient
has not been updated to account for features that we added in Mac OS X 10.6 (!) [1], so it’s clearly not a high priority.

If you do file an ER, please post your bug number here, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Namely, an entry point that that’s equivalent to the

-connection:canAuthenticateAgainstProtectionSpace:
delegate callback.

@eskimo, thanks for the answer. I have filed an enhancement request 35620971.

Would it be possible to implement a work-around using method-swizzling by swizzling [NSURLSession sessionWithConfiguration:delegate:delegateQueue:] method and replacing the |delegate| parameter with a proxy that would forward all method invocations to the original delegate without any changes, except for didFinishCollectingMetrics that would substitute |metrics| with the one created by NSURLProtocol.

I have filed an enhancement request 35620971.

Thanks for that.

Would it be possible … ?

Possible, maybe. A good idea, definitely not. From a binary compatibility standpoint you should stay away from swizzling methods on classes that you don’t own. This is especially true for

NSURLSession
, which already plays games like this internally (notice how, when you
po
an
NSURLSession
instance, the actual type is printed as
__NSURLSessionLocal
or something else that’s not visible to you).

Why not have your protocol provide its own API that allows clients to register for a task metrics callback?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"