I am trying to have my webpage navigate to provided URL. If the URL provides doesn't exist I want my page to redirect to an alternative URL. I need to do this in JavaScript.
This is what I've tried so far:
var customUrl = 'http://www.StackOverflow.com/ThisPageWillResultIn404';
var alternateUrl = 'AlternateUrl.html?e=PageIs404'
setTimeout(function() { window.location=alternateUrl; }, 25);
window.location = customUrl;
This seems to work fine in IOS, but not in Android.
Why Javascript Can't Do This -
If you make requests cross-domain (not from on your site domain) then the requests will fail. This due to a security policy called the "Same-Origin Policy" which is enforced in mainstream browsers to prevent XSS (cross site scripting). A table listed in the Same-Origin Policy Wikipedia page gives a good description of what is considered cross-domain and what is not.
To summarize, client side scripts cannot and should not be able to access sites deemed as cross-domain by the Same-Origin policy.
This means that Javascript will not be able to do what you're asking because it cannot determine anything about the links your users provide unless those links are to your own site.
This seems to work fine in IOS, but not in Android.
While this shouldn't be possible on any device, your current method most likely works because a page that doesn't exist will likely cause the device's browser to linger while it tries to load the non-existent page. While it is still lingering, your code in the timeout runs and redirects. While this is clever, it relies on several assumptions:
The browser will linger when encountering the non-existent page.
The browser will linger for more than 25 milliseconds.
So what's wrong with these assumptions?
You can't assume all browsers will linger. This may explain why Android devices don't seem to work for you. If the server responsible for the link being called is configured to return a 404 page then the page will load normally leaving your script unaware that the link didn't actually exist. For instance, this page doesn't exist, but a 404 page is still returned.
The length of time that a page takes to load also relies on several things such as the connection speed, the browser, the timeout/tolerance the page gives to requests that don't reply, etc. It is likely that clients using your site on a slow connection will be unable to access any sites due to it taking longer than 25 milliseconds to load them while users using a fast connection and a particular browser may experience all pages loading faster than 25 milliseconds thus thwarting your system's intent.
What Can Do This?
The proper solution to this problem requires something to be performed server side. Server side langues can access cross-domain links and determine if the page exists. Stackoverflow user karim79 shows how this can be done with the following PHP snippet (How can I check if a URL exists via PHP?):
$file = 'http://www.domain.com/somefile.jpg';
$file_headers = #get_headers($file);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}
else {
$exists = true;
}
A call from your Javascript with ajax could then be used to send a parameter to the script and then get a response. Obviously minor tweaks would have to be made to the PHP script above to include the parameter and return value.
Lucky for you, Yahoo provides an API driven by YQL, a service they describe as:
Query, filter, and join data across Web services through one simple
language. Eliminate the need to learn how to call different APIs.
Another user looking for a similar solution (Can jQuery/js help me determine if an URL exists) got an answer from Stackoverflow user Sheikh Heera which provided the following solution utilizing the Yahoo API:
function isUrlExists(url)
{
$.getJSON("http://query.yahooapis.com/v1/public/yql?"+
"q=select%20*%20from%20html%20where%20url%3D%22"+
encodeURIComponent(url)+"%22&format=json'&callback=?", function(data){
if(data.results[0]){
alert('Exists');
}
else{
alert('Doesn\'t exist');
}
}
);
}
isUrlExists('http://google.com');
Basically Yahoo will make the request server side and allow you to get the results without you having to write anything server side yourself. This is awesome! This particular example utilizes jQuery, however, it could be done in just plain Javascript.
I've written up a JS-Fiddle with this particular method that seems to work. Check it out:
http://jsfiddle.net/L84RV/embedded/result/
Related
I'm attempting to detect the 'Invalid site key' error for googles re-Captcha via javascript so the error can be reported to the server for further handling. I'm using the explicit rendering mode and calling the api function grecaptcha.render('iframeid', {'site-key':'xxx'});although this function doesn't return any error response or throw an exception even if it loads the following:
I can't simply read the loaded error text either as it's loaded in an iframe on a different domain. Is there anyway to detect an invalid site key automatically, either via javascript or server side?
Edit
Final solution was to load a test page with phantomjs and parse the html of the recaptcha
Google does not provide methods to verify site key, neither you can hack/access reCaptcha html code by JS since the reCapthca is in an iframe and frame's code is not programmatically accessible client-side.
Its a common mistake to forget to update the allowable domains in the dashboard when pushing a new site live.
Since you manage multiple domains I'd recommend you to use one site key for all of the domains you use. Use secure token for that.
Hack
Another option might be that you develop a script that will visit site(s) of interest, make screenshot/snap of loaded reCaptcha, apply OCR (eg. using this) and return a result if site key is valid or not.
As Google does not provide an official way to check this, I've just implemented a workaround performing a GET request on Google's Recaptcha URL. I've made using PHP, but it's not hard to adapt the solution for JavaScript, although it can end on a Cross-Origin error due to Same Origin Policy. So if someone tests this solution using JavaScript, let us know how it goes (and if it does not work, it's always possible to run an AJAX to your own server and check the validity directly from your server).
Besides that, in my case, I'm using Invisible ReCaptcha v2, but I think this approach can be used for other Recaptchas as well.
First, you should mount your URL. I couldn't find a way to determine this "co" param, and I don't know what it means. But it looks like different values are all accepted on different sites. You can look for this value by adding the Recaptcha code on your page (no matter if it's with valid keys or not) and then checking the src param on the generated <iframe>.
$recaptcha_url = sprintf(
'https://www.google.com/recaptcha/api2/anchor?ar=1&k=%s&co=%s&hl=%s&size=%s',
RECAPTCHA_SITE_KEY,
'<co_param_value>',
'en-US',
'invisible'
);
on JavaScript it would be something like this:
recaptcha_url = 'https://www.google.com/recaptcha/api2/anchor?ar=1&k=' + RECAPTCHA_SITE_KEY + ' &co=' + CO_VALUE + '&hl=en-US&size=invisible';
If you are not using Invisible Recaptcha, the size param must be different. But you can also omit it because, at least in my testing, it was not necessary for checking if the Site Key is valid (the same for the language param hl).
Then, you perform a GET request on this URL. On PHP, you can use cURL. If it's Wordpress, you can use wp_remote_get. On JavaScript (jQuery, actually), you can use $.get.
$.get( recaptcha_url, function(data, status){ ... });
Finally, you check if the response body has the string 'Recaptcha.anchor.ErrorMain.init'. This means when the Recaptcha Site Key is not valid for the current domain, Google processes the error, and this string appears on the response body (actually, any ReCaptcha error would result on this string, so remember this is a workaround).
If you are using Wordpress, you can do it with wp_remote_retrieve_body. Something like this:
$response = wp_remote_get( $recaptcha_url );
$response_body = wp_remote_retrieve_body( $response );
if( strpos( $response_body, 'recaptcha.anchor.ErrorMain.init' ) !== false ) {
// Site is not valid for current Recaptcha Keys
}
On JavaScript, I think you can check the data variable received on $.get.
Unfortunately, this is not a strong solution. Google can change both the request and the response, and this could break the implementation. But there is nothing we can do about it as there isn't an official call to check the keys.
I would like to create some javascript that will only run on a given domain. We want to give each of our subscribers a bit of javascript that they can only run on their domain. The javascript will create an iFrame and bring in a page, etc.
If the javascript is placed on a different domain, an error is thrown and the script stops and the iFrame page will not load. Before you say this is not possible, it is done by Google Maps.
So, in short, we would like to mimic what Google Maps is doing. You register a domain with Google, they give you code that has a key and if you place this code on any other domain, it will not work. How do they do it?
The hostname property of window.location contains a hostname. It can be faked, so you could try checking the Referer header when serving your script, too – but absolutely do not rely on that.
You could also do a bit of a validity check by making a request to a nonexistent page on that domain – it’ll be blocked by cross-origin policies if the developer is cheating.
Another possible solution is to use the IP address, since the code is placed on a server.
I've made an license script with this method, and so far only 2 mad customers, but that was because they moved their website to another server without me telling it.
I think its good to have a client check, but that can be by-passed, if someone figures out how the script works. So, always do a server-side check.
Here is some code I use for the license check, its server based.
Also, I removed some functions that are specific to my website.
I can't figure out how to post code so I put it on pastebin.
http://pastebin.com/ftEDXhTP
When you give the user their snippet of code, on the server-side, store a specific domain name with an identifier you give to the user. You will likely generate this code automatically, like StackOverflow did with your question. They called it 19850979, so let's use that as the identifier you give to your user for example. When the user puts the snippet in place, when they use the iframe for example, the URL referenced in the iframe must contain the identifier.
Not sure what your server-side technologies are, but generally this concept works across the board:
For example... your server saves this information in its database:
user-example-domain.com,19850979
Your user's iframe ( which you generate and give them ) references:
your-serving-domain.com/iframeloader/19850979
Now, in the code that handles /iframeloader/ and receives 19850979 as the identifier, compare the hostname of the referrer. This is the Referer header, which is an HTTP header field:
http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
If the hostname of the referrer is value, continue loading the iframe. If not, abort and show some kind of informative error message.
I have created a website for a friend. Because he wished to have a music player continue to play music through page loads, I decided to load content into the page via ajax (facilitated by jQuery). It works fine, it falls back nicely when there is no javascript, and the back/forward buttons are working great, but it's dreadfully slow on the server.
A couple points:
The initial page load is fairly quick. The Chrome developer console tells me that "index.php" loads in about 2.5 seconds. I have it set up so that query string params dictate which page is loaded, and this time frame is approximately accurate for them all. For the homepage, there is 8.4KB of data loaded.
When I load the content in via an ajax request, no matter the size of the data downloaded, it takes approximately 20 seconds. The smallest amount of data that is loaded in this way is about 500 bytes. There is obviously a mismatch here.
So Chrome tells me that the vast majority of the time spent is "waiting" which I take to mean that the server is dealing with the request. So, that can only mean, I guess, that either my code is taking a long time, or something screwy is going on with the server. I don't think it's my code, because it's fairly minimal:
$file = "";
if (isset($_GET['page'])) {
$file = $_GET['page'];
} else if (isset($_POST['page'])) {
$file = $_POST['page'];
} else {
$file = "home";
}
$file = 'content/' . $file . '.php';
if (file_exists($file)) {
include_once($file);
} else {
include_once('content/404.php');
}
This is in a content_loader.php file which my javascript (in this scenario) sends a GET request to along with a "page" parameter. HTML markup is returned and put into a DIV on the page.
I'm using the jQuery .get() shorthand function, so I don't imagine I could be messing anything up there, and I'm confident it's not a Javascript problem because the delay is in waiting for the data from the server. And again, even when the data is very small, it takes about 20 seconds.
I currently believe it's a problem with the server, but I don't understand why a request made through javascript would be so much slower than a request made the traditional way through the browser. As an additional note, some of the content pages do connect to a MySQL database, but some do not. It doesn't seem to matter what the page requires for processing or how much data it consists of, it takes right around 20 seconds.
I'm at a loss... does anyone know of anything that might explain this? Also, I apologize if this is not the correct place for such a question, none of the other venues seemed particularly well suited for the question either.
As I mentioned in my comment, a definite possibility could be reverse DNS lookups. I've had this problem before and I bet it's the source of your slow requests. There are certain Apache config directives you need to watch out for in both regular apache and vhost configs as well as .htaccess. Here are some links that should hopefully help:
http://www.tablix.org/~avian/blog/archives/2011/04/reverse_dns_lookups_and_apache/
http://betabug.ch/blogs/ch-athens/933
To find more resources just Google something like "apache slow reverse dns".
A very little explanation
In a reverse DNS lookup an attempt is made to resolve an IP address to a hostname. Most of the time with services like Apache, SSH and MySQL this is unnecessary and it's a bad idea as it only serves to slow down requests/connections. It's good to look for configuration settings for your different services and disable reverse DNS lookups if they aren't needed.
In Apache there are certain configuration settings that cause a reverse lookup to occur. Things like HostnameLookups and allow/deny rules specifying domains instead of IP addresses. See the links above for more info.
As you suggested in your comment, the PHP script is executing quickly once it finally runs. The time is spent waiting on Apache - most likely to do a reverse DNS lookup, and failing. You know the problem isn't with your code, it's with the other services involved in the request.
Hope this helps!
Ok here's my problem. I'm working on this little site called 10winstreak and I'm trying to detect if a stream is live or not with javascript because our server that we run the site off of cant handle processing every single request with PHP. The basis of detecting if a stream is live or not is you go to their XML file and in one of their tags (if it's live) it will say something along the lines of true and often time the XML file on their site will be empty if a particular stream isn't live. for example if you have a twitch.tv stream for gamespot you go to http://api.justin.tv/api/stream/list.xml?channel=gamespot and if it's got stuff in it then it's live if not then it's not.
so basically my code looks like this:
function check (URL, term){
$.get(URL , function(data){
console.log(data);
//data is whatever the server returns from the request, do whatever is needed with it to show who is live.
var number = data.search(term);
if (number > -1)
{
document.write("Live");
}
else
{
document.write("Offline");
}
});
}
and URL is a url that gets passed in and term is the term to search for in the xml file (usually "true" or "True"). but before anything happens I end up with "XMLHttpRequest cannot load http://api.own3d.tv/liveCheck.php?live_id=6815. Origin (my server's URL) is not allowed by Access-Control-Allow-Origin."
I've looked into it all over the net and i dont seem to be able to find anything that I can use. there's alot of theory stuff but not enough actual code and i dont understand the theory stuff to be able to start typing code out. from what i've seen you have 2 ways to go, use JSONP or add a line somewhere in your sever to allow for cross-domain accessing. neither of which i understand fully nor know how or what to do. It would be alot of help for someone to show me what needs to be done to get rid of this error. of course if you can explain it to a non-coder like me it would be even more awesome but at my current point, as long as the code works for all I care it might as well be magic lol.
You can solve it :)
Take a look at xReader
<script src="http://kincrew.github.com/xReader/xReader.full.js"></script>
<script type="text/javascript">
xReader("http://api.own3d.tv/liveCheck.php?live_id=6815", function(data) {
alert(data.content);
})
</script>
I think you need cacheburst option. but you can be banned from YQL.
I think its because the path is not relative. You may be calling this from a different domain/sub-domain. You can potentially allow other origins to access, which may open up a security hole or you can create a proxy locally.
In PHP creating a proxy is easy: http://blog.proxybonanza.com/programming/php-curl-with-proxy/
Now, instead of directing your request straight to that URL send the request from jQuery to your own local url and have it access it on the server side.
Another option would be to use YQL: http://www.parrisstudios.com/?p=333 (I wrote an article about this a while ago)... In that way you can turn the response into JSON, which can be accessed cross-domain (as can javascript).
You could ask for the API responses to all be returned using a JSONP server and in JSON.
You aren't going to be able to do this via client-side javascript unless they've enabled some way to retrieve their data cross-domain (CORS, JSONP, some flash widgety thing getting read permissions from crossdomain.xml file(s) located on their server...)
Short answer: unless 10winstreak offers a JSONP service, you'll have to do things on the server-side.
Slightly longer answer:
For security reasons browsers won't let you make AJAX requests from www.example.com to www.example2.com (or any other domain except www.example.com). There isn't much you can do about this except use JSONP (and you can only do that if the remote webservice offers it).
Therefore, what you end up needing to do is ask your server "hey what's on that other server?" and (since it's not limited the way a browser is) it can go get the XML from that other server. There are various ways of doing this, either with code or Apache config; not sure what's right for you, but hopefully now you understand the general principle.
P.S. See this question: Wouldn't have been simpler to just discard cookies for cross-domain XHR? if you are curious why browsers do this.
* EDIT *
I just checked out JustinTV's site, and it appears that they already have a PHP library for you to use:
https://github.com/jtvapi/jtv_php_api
This is very likely your best bet (if you want to keep using PHP that is; if not they have libraries for other languages: http://www.justin.tv/p/api).
I'm writing a Greasemonkey script to connect two company-internal webpages. One is SSL, and the other is insecure and can only be accessed via a POST request. If I create a hidden form on the secure page and submit it via an onclick() in an <a>, it works fine, but FF gives a warning:
Although this page is encrypted, the information you have entered is to be sent over an unencrypted connection and could easily be read by a third party.
Are you sure you want to continue sending this information?"
The insecure page can't be accessed via SSL and the other one can't be accessed w/o it, and I can't modify either server =\ Is there any way to avoid this warning by doing some kind of JavaScript/Greasemonkey redirect magic? Thanks!
EDIT: The warning can't be disabled (for rather good reasons, since it's hard to tell if what you're about to send is secure, otherwise). I'm mostly wondering if there's a way to POST in JavaScript without looking like you're submitting a form.
This may be possible by doing a GM_xmlhttpRequest. e.g.,
GM_xmlhttpRequest({
method: 'POST',
url: 'http://your.insecure.site.here',
onload: function(details) {
// look in the JavaScript console
GM_log(details.responseText);
/* This function will be called when the page (url)
has been loaded. Do whatever you need to do with the remote page here.*/
}
});
API/more info here: GM_xmlhttpRequest wiki
You could set up a new SSL site as a proxy that just passes data back to the insecure site. Or just have all your users turn off that particular security warning. (Sorry FF team, but that's not a terribly useful message to start with.)
That's a browser configuration setting, which can't (or shouldn't) be changable by Javascript.
Unless the script needs to be used by more than one user, Tools -> Options -> Security. You can click on settings to display which warning messages are displayed. Note that this currently affects all sites rather then just your internal system.