While going through the book Learning jQuery, 4th Edition, I've been doing the exercises by placing and editing code files in a local directory on the desktop and opening index.html as a file in Firefox.
This worked fine until I had to code an Ajax call that referred to a php file. This required the use of a web server, so I created a subdirectory under the local server root and copied the php file into the subdir.
Keeping all other code on the desktop, I then edited the Ajax call so that it requested from the url
http://localhost/learning-jquery/e.php
The call silently failed and returned nothing. Console windows would show nothing, no errors.
Eventually, I found out about the same-origin policy. In brief, this policy means that by default JavaScript is prevented from making requests across domain boundaries, where same-origin means that the protocol, hostname, and port number must be identical.
So I moved all code files into the subdir under the server root. Working from there rather than the desktop, the Ajax calls then succeeded.
(And I changed the requested url back to just e.php)
***
But what about carrying out
cross-origin access? One possible way is to configure the server to
allow it. For Apache on my Linux system, I added the
following directive in /etc/apache2/apache2.conf
<Directory /var/www/html/learning-jquery>
Header set Access-Control-Allow-Origin "*"
</Directory>
However, checking this configuration change with the command
# apachectl -t
resulted in
AH00526: Syntax error on line 205 of /etc/apache2/apache2.conf:
Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration
Action '-t' failed.
The Apache error log may have more information.
It turns out that I also had to enable a module named headers
# a2enmod headers
Then restart the server. That enabled cross-origin access.
Not yet satisfied, I was wondering if the wildcard "*" in
the directive could be replaced by something more restrictive. For the
way I'm developing locally, the following also works because opening a
file via the file:// protocol results in an origin of null.
<Directory /var/www/html/learning-jquery>
Header set Access-Control-Allow-Origin "null"
</Directory>
***
The fact that the calls had failed silently was very troubling. One way to avoid this is to register a global Ajax error handler by calling ajaxError(). Here's a handler that simply puts up an alert box. (I'm using jQuery 1.9)
$(document).ready(
function setAjaxErrorHandler() {
$(document).ajaxError(
function alertError(event, jqxhr, settings, thrownErr) {
alert('Ajax error handler: ' + jqxhr.status
+ ' ' + jqxhr.statusText);
}
);
}
);
For the cross-origin error, this puts up the message "Ajax error handler: 0 error", which is not exactly super helpful but better than nothing.
Another way is to attach an error handler to the particular request by using the fail() method. For example,
$.get('http://localhost/learning-jquery/e.php', { ... },
function (data) { ... })
.fail(function (jqxhr) {
alert('GET error: ' + jqxhr.status + ' '
+ jqxhr.statusText);
});
Sources:
jQuery.get()
https://api.jquery.com/jQuery.get/
Same-origin policy
https://en.wikipedia.org/wiki/Same-origin_policy
Why is CORS important?
http://enable-cors.org/
CORS on Apache
http://enable-cors.org/server_apache.html
Configure Apache To Accept Cross-Site XMLHttpRequests on Ubuntu
https://harthur.wordpress.com/2009/10/15/configure-apache-to-accept-cross-site-xmlhttprequests-on-ubuntu/
Super helpful! Perhaps the error handling could be added to the module?
ReplyDeleteThat's a good idea to look into adding error handling to the JS code for the Optimizely module.
ReplyDelete