I have seen all sorts of questions about modifying NSURLRequest but not NSHTTPURLResponse. Our scenario is that:
A web page that is loaded in a UIWebview will make an HTTP request. This is typically a form post in a hidden iFrame or AJAX request. All that we can control is the host name of the request. We cannot modify anything else in the webpage.
In the UIWebviewDelegate the request is captured. We extract some data out of the request URL. That data is processed and a result is generated.
Then I need to provide a custom NSHTTPURLResponse that includes the result from #2 to the web view.
This is similar to the basic functionality of a Java Servlet.
I have not found any way of being able to achieve #3.
Also UIWebviewDelegate doesn't seem to capture AJAX requests. There doesn't seem to be any workaround without placing custom java script in the web page as outlined here: UIWebViewDelegate not monitoring XMLHttpRequest?
Related
The iOS application we have has a WkWebview that tries to communicate with our server by calling a https endpoint. The server works similar to a proxy and all calls to our endpoint will then forward the request to the destination site. For example - in our app if we were to set our destination to https://www.google.com the application will translate that to https://server.com/http://www.google.com.
The problem we are trying to solve is the interception of all http/https calls after the original WkWebview call. This includes all resource calls like css and javascript files. We have tried to use a custom scheme handler but since we do not parse the html/css on the server side we cannot add a custom scheme to intercept all http/https calls.
You can add the interception logic inside the webview for example every request store url and current number of calls inside a hidden element , and check it's value periodically by evaluteJavaScript function of the webview for that element
I'm having some issues with video requests handled through a special protocol scheme in a NSURLProtocol subclass. Every other resource (images/text) are getting handled correctly, however, when a video request is sent, I only get a call to 'canInitWithRequest' and no follow up. So, my video resource doesn't get resolved. Now, I've looked around and I found no definite solution for this. Some people use instead an embedded HTTP server, but that seems an overkill. Does anyone know if this is a bug or if not, why is this limitation, is there an workaround for it?
A similar issue: Custom NSURLProtocol class for WebView doesn't work when loading video in HTML5 document , but unfortunately without an answer.
#Meda, I was facing the similar issue. Here what I found and hope it is useful to you.
I assume that you are using NSUrlProtocol because you want to intercept the video requests.
I was using web view which makes request for video over HTTP. It goes to NSURLProtocol and makes the request. When it receives the data, webView loads the video rendering plugin (looking at the mime type in HTTP header). The plugin needs the data to come as Partial HTTP response (Response code 206). Further, the plugin does not use NSURLProtocol class but uses network layer below it. So requests that plugin makes, do not go thru NSURLProtocol. Considering this, there could be 2 problems in your case.
1. HTTP server you are using may not be supporting partial responses.
2. HTTP server is not reachable directly (Can you access the video from safari or any other
browser on your device?)
You can verify both the cases by taking network trace. use tcpdump (available on Mac) to take network trace and see what is happening there.
I'm looking for a way to use NSMutableURLRequest with app level proxyHost/Port settings, essentially a replacement for ASIHTTPRequest lib with proxyHost/proxyPort. I've tried modifying the CFReadStream (from NSURLRequest HTTPBodyStream), but it SIGSEGs when setting the proxy settings. I would rather not have to rewrite my app with CFNetworking, and it looks like AFNetwork lib doesn't include this feature yet either.
Has anyone successfully done this with NSMutableURLRequest?
The real answer appears to be creating a custom NSURLProtocol. Should be a straight forward derivation, and add the appropriate proxyHost/proxyPort to the request (along with any other values such as a customized User Agent string). Then, supposedly, all requests will be routed through this custom protocol (including UIWebView requests..direct or derived).
relevant samples:
https://developer.apple.com/library/ios/samplecode/CustomHTTPProtocol/Introduction/Intro.html#//apple_ref/doc/uid/DTS40013653
http://eng.42go.com/customizing-uiwebview-requests-with-nsurlprotocol/
I'll post more when I have the thing operational.
Things of note with this implementation.
Initially started using CFNetworking as the "wedge" in my custom
NSURLPRotocol, but quickly found I was rewriting the same code that
was in ASIHTTPRequest. So I just implemented the wedge with
ASIHTTPRequest.
The items that are not documented well (or at all), is the
interaction of UIWebView with NSURLProtocol callbacks, vs
NSURLRequest/Conenction with NSURLProtocol. Some Findings:
a) All dependent page resources are loaded automatically by UIWebView
(which we knew), and they all go through NSURLProtocol, so it is an
excellent place to put in code to modify all requests.
b) The UIWebView sets the Referer header. On a redirect, the only
way to get the UIWebView to update it's Referer from the original URL
to the new redirect URL is with the [[self client] URLProtocol:self
wasRedirectedToRequest:redirectRequest
redirectResponse:tmpHttpResponse]; callback.
c) when the above redirect callback is received by UIWebView, it
generates a new NSURLRequest (essentially the one you sent back to
it). So if you have a wedge that likes to do the redirect
internally, you have to cancel the Request that it attempts to make,
in favor of the new one from UIWebView.
You have to be careful with which callbacks you implement from ASIHTTPRequestDelegate. e.g. implementing didReceiveData will disable the built in gzip processing. willRedirectToURL disables most of the built in redirect processing (even if you call [request redirectToURL:newURL]; as recommended in the comments).
Is it possible to read the http request and response data from pages loading inside webview. What i want to do is get the binary data from a response after user clicks on a link inside the page in webview. Any help or clue would be greatly appreciated
Create your own URLStreamHandlerFactory initialized by URL.setURLStreamHandlerFactory which generates a URLStreamHandler that wraps the standard http and https URLStreamHandlers to intercept their traffic before forwarding.
Some of the concepts are explained in A New Era for Java Protocol Handlers whitepaper.
Another option is to listen to the WebEngine.location property and open a separate connection to a server to retrieve and process the binary data as needed. An example of this approach is the pdf handling code for the willow web browser.
So I'm writing a post on my wall and type a URL into the main body of the post. As soon as I finish the URL, Facebook creates a little section underneath which has the title, description, and an image from the url I typed.
Without getting too indepth, how is this done and what is the best way of make something similar myself?
jQuery (or some other framework that lets you do Ajax easily) to communicate between browser client and webserver
PHP/ASP.NET/Python (or some other scripting framework on the backend) to fetch the url
Facebook also has a meta data specification you might be interested in, to let developers further define what gets shown in a Facebook page.
I believe Facebook is written in PHP. And PHP does this easily.
FOpen can be used to access files on other sites. There are other functions but this will get you started. Then it's a matter of parsing the html you get from the url to get what you want.
http://php.net/manual/en/function.fopen.php
You have a couple choices. You can fetch it using Ajax from the client; or you can fetch it from your server.
If doing it from your server in asp.net then you need to use HttpWebRequest.
FB does an asynchronous JavaScript call to fetch that data without reloading the window you're on. Lookup ajax and libraries like jquery do this: http://api.jquery.com/category/ajax/