Get the current full URL for WKWebView - wkwebview

Is there a way to get the FULL URL loaded by a WKWebView for every request?
webView:didFinishNavigation:
Works only for mainFrame navigations and does not provide a URL request parameter.
How do I get the FULL URL just like in UIWebViewDelegate's
webViewDidFinishLoad:webView
...which gets invoked after any loading finishes and you can get the full request URL from the webView parameter.
It's nice that WKWebView's URL property saves the work that needs to be done to extract a UI-friendly base URL, but it's a huge loss we can't get the full one!
I have tried using
webView:decidePolicyForNavigationAction:decisionHandler:
...but it produces different results for URLs compared to what a UIWebView's request property holds after finishing the load of a page.

You can get URL for a newly requested Webpage by "navigationAction.request.URL" in decidePolicyForNavigationAction delegate method.
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
if let urlStr = navigationAction.request.URL?.absoluteString{
//urlStr is what you want, I guess.
}
decisionHandler(.Allow)
}

First, I think you are confusing NSURL and NSURLRequest. The first is readily accessibly via webView.URL and it does actually give you the full URL of whatever was loaded. Assuming that where you say URL you mean NSURL.
If that is not what you meant, for example if you wanted to see the redirect chain or the response headers, then I'm afraid the answer is that you cannot get to tht specific information via the WKWebView.
You will have to fall back to UIWebView where you can intercept requests relatively easily and see the full request/response.

This is Yuichi Kato's answer for Swift 4. It retrieves the full URL from the request property of the navigation action in the webView(_:decidePolicyFor:decisionHandler:) method of WKNavigationDelegate.
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let urlStr = navigationAction.request.url?.absoluteString {
//urlStr is what you want
}
decisionHandler(.allow)
}
Don't forget to conform your class to WKNavigationDelegate and set your web view's delegate accordingly:
class WebViewController: UIViewController, WKNavigationDelegate
[...]
webView.navigationDelegate = self

Related

UiWebView response to window.print

Is there a way to detect window.print from a UIWebView and respond to it? I have printing in my UiWebView and need to have a way to react to that event from the UIWebView.
First, this is the solution I came across. But UIWebview does not support those events and the API like in a desktop browser. And haven't yet got the matchMedia to work. Probably will work when I have a printer configured!?!.
The actual reason is that the media type of the web page did not change from screen to print in the UIWebView, unlike desktop browsers, so there is no trigger, till this point.
And UIWebView has no delegate method for printing exposed till date.
Anyways, where there is a will, there is a [hack] way. Two step solution.
Step 1. Javascript
If you have access to the HTML or JS file, and it is used only for this UIWebView, you can add the below lines to the JS
(function(){
var originalPrintFn = window.print; // Keep it cached in this variable, just in case
window.print = function(){
// Trigger location change
window.location = "your_app_scheme:print";
}
})();
If you don't have access to the HTML or JS file, in your UIWebView delegate, add the below code
[self.myWebView stringByEvaluatingJavaScriptFromString:#"(function(){var originalPrintFn = window.print;window.print = function(){window.location = 'your_app_scheme:print';}})();"];
This can be done in the delegate's webViewDidFinishLoad method
Step 2. Catching the call in native
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] absoluteString] hasPrefix:#"your_app_scheme:"]) {
// Call the given selector
[self performSelector:#selector(your_handle_to_print)];
// Cancel the event, so the webview doesn't load the url
return NO;
}
return YES;
}
After this in your_handle_to_print, you can do your printing magic.
Hope this helps!

Get real requestURI without appended index.xhtml when welcome file is used

So here are 2 requests:
http://example.com/someUrl/
http://example.com/someUrl/index.xhtml (xhtml extension is not relevant just an example)
When the <welcome-file>index.xhtml</welcome-file> is been set, request 1 is handled by the server as 2.
However, in both cases the request.getRequestURI() returns the complete URI: someUrl/index.xhtml.
According to documentation it shouldn't but in most cases it's what we want so it seems fine it does.
I'm working with JSF under JBoss Wildfly (Undertow webservice) and I don't know which one is responsible.
I don't necessarily want to change how it works but I'm looking for a way of getting the original URI as the enduser sees in browser address bar, thus without the index.xhtml part in case of 1.
To be more precise, I have to get the exact same URL as returned by document.location.href in JavaScript.
The welcome file is been displayed by a forward which is under the server's covers been performed by RequestDispatcher#forward(). In that case, the original request URI is available as a request attribute with a key as identified by RequestDispatcher#FORWARD_REQUEST_URI, which is javax.servlet.forward.request_uri.
So, this should do:
String originalURI = request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if (originalURI == null) {
originalURI = request.getRequestURI();
}
// ...

Web API action filter content can't be read

Related question: Web API action parameter is intermittently null and http://social.msdn.microsoft.com/Forums/vstudio/en-US/25753b53-95b3-4252-b034-7e086341ad20/web-api-action-parameter-is-intermittently-null
Hi!
I'm creating a ActionFilterAttribute in ASP.Net MVC WebAPI 4 so I can apply the attribute in action methods at the controller that we need validation of a token before execute it as the following code:
public class TokenValidationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext filterContext)
{
//Tried this way
var result = string.Empty;
filterContext.Request.Content.ReadAsStringAsync().ContinueWith((r)=> content = r.Result);
//And this
var result = filterContext.Request.Content.ReadAsStringAsync().Result;
//And this
var bytes = await request.Content.ReadAsByteArrayAsync().Result;
var str = System.Text.Encoding.UTF8.GetString(bytes);
//omit the other code that use this string below here for simplicity
}
}
I'm trying to read the content as string. Tried the 3 ways as stated in this code, and all of them return empty. I know that in WebApi I can read only once the body content of the request, so I'm commenting everything else in the code, and trying to get it run to see if I'm getting a result. The point is, the client and even the Fiddler, reports the 315 of the content length of the request. The same size is getting on the server content header as well but, when we try read the content, it is empty.
If I remove the attribute and make the same request, the controller is called well, and the deserialization of Json happens flawless. If I put the attribute, all I get is a empty string from the content. It happens ALWAYS. Not intermittent as the related questions state.
What am I doing wrong? Keep in mind that I'm using ActionFilter instead of DelegatingHandler because only selected actions requires the token validation prior to execution.
Thanks for help! I really appreciate it.
Regards...
Gutemberg
By default the buffer policy for Web Host(IIS) scenarios is that the incoming request's stream is always buffered. You can take a look at System.Web.Http.WebHost.WebHostBufferPolicySelector. Now as you have figured, Web Api's formatters will consume the stream and will not try to rewind it back. This is on purpose because one could change the buffer policy to make the incoming request's stream to be non-buffered in which case the rewinding would fail.
So in your case, since you know that the request is going to be always buffered, you could get hold of the incoming stream like below and rewind it.
Stream reqStream = await request.Content.ReadAsStreamAsync();
if(reqStream.CanSeek)
{
reqStream.Position = 0;
}
//now try to read the content as string
string data = await request.Content.ReadAsStringAsync();

Chrome extension, onbeforerequest, which page is making the call?

Im making a small google chrome extension that is watching all calls a page is making. The idea is to log how a page behaves and how many external calls are made. Got everything working except the part where i need to get the source url of the page that initiates the call.
For example im going to www.stackoverflow.com in my browser, then my onbeforerequest lister kicks in and gives me all the calls. So far so good. But i still want the name of the page which is making the calls, in this case i want: "www.stackoverflow.com" and the owner of the calls.
I tried getting it from the tabs, but chrome.tabs.get uses a callback and that is not called before its all over and i got all the calls processed.
any ideas on how to get the source url?
edit
Im using this code right now, to get the url, but it keeps returning "undefined":
var contentString = "";
chrome.webRequest.onBeforeRequest.addListener(
function (details) {
var tabid = details.tabId;
var sourceurl = "N/A";
if (tabid >= 0) {
chrome.tabs.get(parseInt(tabid), function (tab) {
sourceurl = tab.url;
alert(sourceurl);
});
}
});
When doing the alert, i get undefined for every request
edit 2 - this is working for me
chrome.tabs.get(parseInt(tabid), function (tab) {
if (tab != undefined) {
alert(tab.url);
}
});
onBeforeRequest returns a TabID, then you can then use the get method of the tabs API to get a reference to the tab and thus the URL of the page.
You can use the details.initiator (see here for more details) which is supported since Chrome 63 version. Below you can see what is mentioned on Chrome APIs page about the initiator.
The origin where the request was initiated. This does not change
through redirects. If this is an opaque origin, the string 'null' will
be used.

Persist url parameter throughout grails app

Essentially I am looking to have a url query parameter persist throughout the life of the grails application (POST or GET). ex.
http://localhost:8080/demo/controller/action/?myParam=foobar
I have tried a couple routes. Dynamic method overriding redirect and customizing application tags for createLink. However, since I also use grails webflows it doesn't quite get every single URL. I also tried using a groovy servlet (groovlet) to capture every URL and append the query parameter. The last attempt hasn't been very successful. Am I missing an obvious component to grails? Am I on the right track? Is there another avenue I haven't explored yet?
Thanks in advance
Have you tried using a filter? The following filter will add the param to every request
class MyFilters {
def filters = {
addParam(controller:'*', action:'*') {
before = {
params.myParam = 'foobar'
}
} } }

Resources