I have an app where I need to add a custom request header for all outgoing requests from UIWebView. I believe the way to accomplish this is to use a custom NSUrlProtocol.
My example below is "working" but has issues, and I'm not quite sure what they are to be honest. I'm getting some intermittent loading issues where sometimes a WebView will load but other times it will not. I'm not sure if this is a garbage collection issue or not, but I can't seem to pin anything down. It seems to happen on devices and not the debugger, so I can't really track down what is happening as well.
I'm not sure if all of what I'm doing in my example is necessary. I only need to add the header...if there is a more simple way to accomplish this, please let me know.
Thanks!
public class MyCustomUrlProtocol : NSUrlProtocol
{
private NSUrlConnection connection;
private MyCustomConnectionDelegate connDelegate;
[Export ("canInitWithRequest:")]
public static bool canInitWithRequest (NSUrlRequest request)
{
if (null != request.Headers && request.Headers.ContainsKey (NSObject.FromObject ("MyCustomHeader"))) {
return false; // request has already been handled
}
return true;
}
[Export ("canonicalRequestForRequest:")]
public static new NSUrlRequest GetCanonicalRequest (NSUrlRequest request)
{
return request;
}
[Export ("initWithRequest:cachedResponse:client:")]
public MyCustomUrlProtocol (NSUrlRequest request, NSCachedUrlResponse cachedResponse, NSUrlProtocolClient client)
: base (request, cachedResponse, client)
{
}
public override void StartLoading ()
{
if (null == connDelegate) {
connDelegate = new MyCustomConnectionDelegate (this);
}
// inject the ]HTTP header
NSMutableDictionary headers = new NSMutableDictionary (Request.Headers);
headers.Add(NSObject.FromObject("MyCustomHeader"), NSObject.FromObject ("MyCustomValue"));
NSMutableUrlRequest newRequest = (NSMutableUrlRequest)Request.MutableCopy ();
newRequest.Headers = headers;
this.connection = new NSUrlConnection (newRequest, connDelegate, true);
}
public override void StopLoading ()
{
if (this.connection != null) {
this.connection.Cancel ();
this.connection = null;
}
}
protected override void Dispose (bool disposing)
{
StopLoading ();
}
private class MyCustomConnectionDelegate : NSUrlConnectionDelegate
{
private MyCustomUrlProtocol handler;
public MyCustomConnectionDelegate (MyCustomUrlProtocol handler) {
this.handler = handler;
}
public override void ReceivedData (NSUrlConnection connection, NSData data)
{
handler.Client.DataLoaded (handler, data);
}
public override void FailedWithError (NSUrlConnection connection, NSError error)
{
handler.Client.FailedWithError (handler, error);
handler.StopLoading ();
}
public override void ReceivedResponse (NSUrlConnection connection, NSUrlResponse response)
{
handler.Client.ReceivedResponse (handler, response, NSUrlCacheStoragePolicy.NotAllowed);
}
public override void FinishedLoading (NSUrlConnection connection)
{
handler.Client.FinishedLoading (handler);
handler.StopLoading ();
}
protected override void Dispose (bool disposing)
{
handler.StopLoading ();
}
}
}