Please subscribe to RSS Feed! :)

I was reading a PCPro magazine recently and one of the editors wrote down his ‘programming language timeline’.
What is that you ask? A timeline in chronological order of the programming languages you have learned.
I found myself thinking about this last night and realised I have a strange one (okay so HTML and CSS are markup languages!):
HTML > CSS > Javascript > GML > Python > Vala/Genie
What is your programming language timeline? I would be interested to see if we have even more diverse ones!

Selenium is quite a famous testing tool and has a lot of documentation (so I
wont bother to repeat stuff from there). I'll just focus on the bits where I
feel the documentation could improve.
STEP#0.After downloading selenium remotecontrol
change to the directory. {to install selenium on you local machine, download selenium from here.}
~$ cd selenium-remote-control-1.0.3/
~/selenium-remote-control-1.0.3/selenium-server-1.0.3$ sudo java -jar
selenium-server.jar
09:03:05.618 INFO - Java: Sun Microsystems Inc. 1.6.0_0-b11
09:03:05.638 INFO - OS: Linux 2.6.24-28-generic i386
09:03:05.722 INFO - v2.0 [a2], with Core v2.0 [a2]
09:03:06.304 INFO - RemoteWebDriver instances should connect to:
http://192.168.1.5:4444/wd/hub
09:03:06.307 INFO - Version Jetty/5.1.x
09:03:06.311 INFO - Started
HttpContext[/selenium-server/driver,/selenium-server/driver]
09:03:06.324 INFO - Started
HttpContext[/selenium-server,/selenium-server]
09:03:06.324 INFO - Started HttpContext[/,/]
09:03:06.381 INFO - Started
org.openqa.jetty.jetty.servlet.ServletHandler@12d15a9
09:03:06.382 INFO - Started HttpContext[/wd,/wd]
09:03:06.399 INFO - Started SocketListener on 0.0.0.0:4444
09:03:06.400 INFO - Started
org.openqa.jetty.jetty.Server@228a02
I wanted to run the python script from the console and each time it would
stop here and I'd be waiting and nothing would happen.....How do I run the
script without a command prompt. So then, I'd interrupt it with 'ctrl C' to get
a "09:03:17.439 INFO - Shutting down...12:39:08.573 INFO - Stopping
Acceptor ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=4444]
That "shutting down" message was odd -- how would you run a process if it
was shutting down? What the logs above dont say is "The selenium server must be
running so keep that process open. Open ANOTHER terminal window and run your
python script there". The documentation didnt explicitly mention that localhost
must keep the server running in the background-- Its one of the most basic
client-server concepts but when you are running stuff on localhost, your client
and server are one and the same. Being explicit with this trivia in the
documentation would have helped me not waste hundreds of hours searching the
selenium website and reading irrelevant blogs which google threw up, irc,
emails, etc... So, in TerminalOne,
:~/selenium-remote-control-1.0.3/selenium-server-1.0.3$ sudo java -jar
selenium-server.jar
09:03:05.618 INFO - Java: Sun Microsystems Inc. 1.6.0_0-b11
09:03:05.638 INFO - OS: Linux 2.6.24-28-generic i386
09:03:05.722 INFO - v2.0 [a2], with Core v2.0 [a2]
09:03:06.304 INFO - RemoteWebDriver instances should connect to:
http://192.168.1.5:4444/wd/hub
09:03:06.307 INFO - Version Jetty/5.1.x
09:03:06.311 INFO - Started
HttpContext[/selenium-server/driver,/selenium-server/driver]
09:03:06.324 INFO - Started
HttpContext[/selenium-server,/selenium-server]
09:03:06.324 INFO - Started HttpContext[/,/]
09:03:06.381 INFO - Started
org.openqa.jetty.jetty.servlet.ServletHandler@12d15a9
09:03:06.382 INFO - Started HttpContext[/wd,/wd]
09:03:06.399 INFO - Started SocketListener on 0.0.0.0:4444
09:03:06.400 INFO - Started org.openqa.jetty.jetty.Server@228a02
09:03:17.439 INFO - Shutting down...
mom@drga:~/selenium-remote-control-1.0.3/selenium-server-1.0.3$ sudo java -jar
selenium-server.jar
09:03:36.248 INFO - Java: Sun Microsystems Inc. 1.6.0_0-b11
09:03:36.252 INFO - OS: Linux 2.6.24-28-generic i386
09:03:36.270 INFO - v2.0 [a2], with Core v2.0 [a2]
09:03:36.486 INFO - RemoteWebDriver instances should connect to:
http://192.168.1.5:4444/wd/hub
09:03:36.489 INFO - Version Jetty/5.1.x
09:03:36.491 INFO - Started
HttpContext[/selenium-server/driver,/selenium-server/driver]
09:03:36.493 INFO - Started
HttpContext[/selenium-server,/selenium-server]
09:03:36.493 INFO - Started HttpContext[/,/]
09:03:36.523 INFO - Started
org.openqa.jetty.jetty.servlet.ServletHandler@12d15a9
09:03:36.523 INFO - Started HttpContext[/wd,/wd]
09:03:36.533 INFO - Started SocketListener on 0.0.0.0:4444
09:03:36.533 INFO - Started org.openqa.jetty.jetty.Server@228a02
09:04:30.236 INFO - Checking Resource aliases
09:04:30.260 INFO - Command request: getNewBrowserSession[*firefox,
http://localhost:4444, ] on session null
09:04:30.283 INFO - creating new remote session
09:04:30.614 INFO - Allocated session 7cba6a7dadb243618c046ee7fb6c6bc9 for
http://localhost:4444, launching...
09:04:30.778 INFO - Preparing Firefox profile...
09:04:34.676 INFO - Launching Firefox...
09:04:38.697 INFO - Got result: OK,7cba6a7dadb243618c046ee7fb6c6bc9 on session
7cba6a7dadb243618c046ee7fb6c6bc9
09:04:38.715 INFO - Command request:
open[/selenium-server/tests/html/test_click_page1.html, ] on session
7cba6a7dadb243618c046ee7fb6c6bc9
09:04:38.854 INFO - Got result: XHR ERROR: URL =
http://localhost:4444/selenium-server/tests/html/test_click_page1.html
Response_Code = 404 Error_Message = Not+found on session
7cba6a7dadb243618c046ee7fb6c6bc9
09:04:38.863 INFO - Command request: testComplete[, ] on session
7cba6a7dadb243618c046ee7fb6c6bc9
09:04:38.863 INFO - Killing Firefox...
09:04:38.933 INFO - Got result: OK on session
7cba6a7dadb243618c046ee7fb6c6bc9
09:09:28.085 INFO - Command request: getNewBrowserSession[*firefox,
http://www.irian.at, ] on session null
09:09:28.086 INFO - creating new remote session
09:09:28.088 INFO - Allocated session 97dec9f0b53545acbc9ca3624fc6cbd4 for
http://www.irian.at, launching...
09:09:28.165 INFO - Preparing Firefox profile...
09:09:31.873 INFO - Launching Firefox...
09:09:35.599 INFO - Got result: OK,97dec9f0b53545acbc9ca3624fc6cbd4 on session
97dec9f0b53545acbc9ca3624fc6cbd4
09:09:35.604 INFO - Command request:
open[http://www.irian.at/selenium-server/tests/html/ajax/ajax_autocompleter2_test.html,
] on session 97dec9f0b53545acbc9ca3624fc6cbd4
09:09:41.698 INFO - Got result: XHR ERROR: URL =
http://www.irian.at/selenium-server/tests/html/ajax/ajax_autocompleter2_...
Response_Code = 404 Error_Message = Not Found on session
97dec9f0b53545acbc9ca3624fc6cbd4
09:09:41.707 INFO - Command request: testComplete[, ] on session
97dec9f0b53545acbc9ca3624fc6cbd4
09:09:41.707 INFO - Killing Firefox...
09:09:41.740 INFO - Got result: OK on session
97dec9f0b53545acbc9ca3624fc6cbd4
10:18:38.252 INFO - Command request: getNewBrowserSession[*firefox,
http://www.google.com/, ] on session null
10:18:38.253 INFO - creating new remote session
10:18:38.254 INFO - Allocated session c4b9c7f35ea34d428b50f2f31a6181c2 for
http://www.google.com/, launching...
10:18:38.322 INFO - Preparing Firefox profile...
10:18:41.921 INFO - Launching Firefox...
10:18:45.741 INFO - Got result: OK,c4b9c7f35ea34d428b50f2f31a6181c2 on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:45.800 INFO - Command request: open[http://www.google.com/, ] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.204 INFO - Got result: OK on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.211 INFO - Command request: type[q, hello world] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.277 INFO - Got result: OK on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.282 INFO - Command request: click[btnG, ] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.334 INFO - Got result: OK on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:47.340 INFO - Command request: waitForPageToLoad[5000, ] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:48.359 INFO - Got result: OK on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:48.365 INFO - Command request: getTitle[, ] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:48.411 INFO - Got result: OK,hello world - Google Search on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:48.416 INFO - Command request: testComplete[, ] on session
c4b9c7f35ea34d428b50f2f31a6181c2
10:18:48.417 INFO - Killing Firefox...
10:18:48.434 INFO - Got result: OK on session
c4b9c7f35ea34d428b50f2f31a6181c2
ALL this happens on TerminalOne, so keep that window open to check for the
above while you are doing steps below.
STEP#1. In TerminalTwo, Change directory to the
'python-client' to run your scripts. Lets test the selenium.py script first.
Btw, note that your bash file must contain the PYTHONPATH for all the
directories that you run .py scripts from.
:~/selenium-remote-control-1.0.3$ ls
README.txt selenium-php-client-driver-1.0.1
selenium-dotnet-client-driver-1.0.1
selenium-python-client-driver-1.0.1
selenium-java-client-driver-1.0.1 selenium-ruby-client-driver-1.0.1
selenium-perl-client-driver-1.0.1 selenium-server-1.0.3
:~/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1$ python
selenium.py
If it returns silently (read, No errors), it means your selenium server is
working.
STEP#2. Try testing another script, test_google.py
or test_default_server.py
:~/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1$ ls
doc test_ajax_jsf.py test_google.py~
selenium.py test_ajax_jsf.pyc test_google.pyc
selenium.pyc
test_default_server.py test_i18n.py
selenium_test_suite_headless.py test_default_server.pyc
test_i18n.pyc
selenium_test_suite.py test_google.py
:~/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1$ python
test_default_server.py
Using selenium server at localhost:4444
E
======================================================================
ERROR: testLinks (__main__.TestDefaultServer)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_default_server.py", line 36, in testLinks
selenium.open("/selenium-server/tests/html/test_click_page1.html")
File
"/home/me/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1/selenium.py",
line 764, in open
self.do_command("open", [url,])
File
"/home/me/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1/selenium.py",
line 215, in do_command
raise Exception, data
Exception: XHR ERROR: URL =
http://localhost:4444/selenium-server/tests/html/test_click_page1.html
Response_Code = 404 Error_Message = Not+found
----------------------------------------------------------------------
Ran 1 test in 8.852s
FAILED (errors=1)
:~/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1$ python
test_ajax_jsf.py
Using selenium server at localhost:4444
E
======================================================================
ERROR: testKeyPress (__main__.TestAjaxJSF)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_ajax_jsf.py", line 39, in testKeyPress
selenium.open("http://www.irian.at/selenium-server/tests/html/ajax/ajax_autocompleter2_test.html")
File
"/home/me/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1/selenium.py",
line 764, in open
self.do_command("open", [url,])
File
"/home/me/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1/selenium.py",
line 215, in do_command
raise Exception, data
Exception: XHR ERROR: URL =
http://www.irian.at/selenium-server/tests/html/ajax/ajax_autocompleter2_...
Response_Code = 404 Error_Message = Not Found
----------------------------------------------------------------------
Ran 1 test in 13.663s
FAILED (errors=1)
:~/selenium-remote-control-1.0.3/selenium-python-client-driver-1.0.1$ python
test_google.py
.
----------------------------------------------------------------------
Ran 1 test in 10.190s
OK
When you are running the above scripts you would see Selenium
throw a browser with messages but this is too fast and disappears. In the
second terminal, run your scripts from the directory you've stored
them in.

Request Tracker is a really neat support tool, but one of the common complaints I heard from people using it during a previous project was that it was pretty slow.
There wasn't much we could do about the (overloaded) server it was running on, but I found that enabling mod_deflate really helped.
After watching this great video though, I was inspired to look into it a bit more, focussing this time on latency.
Also note that I was looking for the "best case" for each of the different configurations and so each screenshot was taken after reloading the homepage 10-20 times to maximize cache hits (thanks in large part to mod_expires).
(Is there a nice automated way of measuring average latency?)
Using the default apache2-modperl2 config file (as supplied by RT), here's what the homepage (logged in as root) looked like before I changed anything:
The purple section here indicates the time spent waiting for the server. This shows that the server (running Mason inside mod_perl) is doing quite a bit of processing, including a lot more work than you'd expect while serving static files. It's quite impressive to see how fast the images are being served (directly by Apache) in comparison with the Javascript and the CSS files (which go through Mason).
The reason while Javascript and CSS files have to be served by mod_perl is that they are in fact templates. They contain a few Mason variables which must be substituted before being served.
Looking into it further though, all of these replacements have to do with variables defined in RT_SiteConfig.pm (mostly the install path). Here's an example:
var path = "" ? "" : "/";
which gets turned into:
var path = "/rt" ? "/rt" : "/";
So as long as these paths don't change, then there is no need to re-generate these files.
This next diagram was produced after configuring Apache to serve all Javascript and CSS files directly from Apache:
The way I did that (without modifying any of the original files) was by saving the Javascript/CSS sent to the browser and using mod_rewrite rules to serve these files instead of the original templated ones:
# Serve static files directly
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/ahah.js$ /var/www/rt/ahah.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/cascaded.js$ /var/www/rt/cascaded.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/class.js$ /var/www/rt/class.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/combobox.js$ /var/www/rt/combobox.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/list.js$ /var/www/rt/list.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/titlebox-state.js$ /var/www/rt/titlebox-state.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/js/util.js$ /var/www/rt/util.js
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/css/3.5-default/main-squished.css$ /var/www/rt/main-squished.css
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/css/print.css$ /var/www/rt/print.css
RewriteRule ^/usr/share/request-tracker3.6/html/NoAuth/webrtfm.css$ /var/www/rt/webrtfm.css
Removing unnecessary images
Finally, one thing I noticed from this last graph is that the rounded corners in the theme require a number of small images. While these don't take a whole lot of bandwidth, they do require quite a bit of back and forth between the browser and the server.
So I replaced all of the "rounded corner" images in the main-squished.css file with the following CSS attributes:
-moz-border-radius-topleft: 8px;
-moz-border-radius-topright: 8px;
-moz-border-radius-bottomleft: 8px;
-moz-border-radius-bottomright: 8px;
-webkit-border-top-left-radius: 8px;
-webkit-border-top-right-radius: 8px;
-webkit-border-bottom-left-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
(yes, Internet Explorer users probably don't get the rounded corners... oh well)
This eliminated a number of roundtrips and shaved off a few more milliseconds:
By this stage, the pages are pretty snappy so there is not much to be gained anymore, but I figured I'd try to reduce the latency a bit more by combining all Javascript files into one (and doing the same for CSS files with the exception of print.css). This is what I got:
(Note that I also took the opportunity to minify both squished files to reduce the filesize.)
Not a huge improvement and I unfortunately had to copy quite a few Mason templates from /usr/share/request-tracker3.6/html/ to /usr/local/share/request-tracker3.6/html/ and then replace all of the script tags with a single one in html/Elements/Header.
I've stopped here, but there might be ways to further reduce the processing time on the server (hence the latency) by tuning mod_perl/Mason or Postgres. The RT wiki also has a few pointers.
Replacing Apache with Nginx (which means moving to FastCGI) was something I considered, but after trying it out, it turned out that it would add about 100ms of extra latency.
Feel free to leave a comment if you've found something else that makes a big difference on your site.

Woooooooooooo!
(Translated : an awesome guy called Frederik on the Vala mailing list has just sent me a vapi file that allows binding of Javascript functions to Vala/Genie functions)
(Translated: I can continue developing Wasiliana!)
This doesn’t mean I shall stop on kazam, but there shall be less progress. On the kazam front, I have developed the start window (where you select audio/video sources), the countdown window and indicator and I have settled on the lossless format to write to disk. I can show you something pretty soon…

In Dayton, we don't have a dedicated Python user group; instead, we have the Dynamic Languages User Group. I always struggle to explain why I enjoy this group so much, because a quick description doesn't sound that impressive. Each meeting is 5-10 people scattered across the entire dynamic language landscape: Python, Ruby, Perl, JavaScript, PHP... now and then somebody will throw in some LISP or whatnot. There's only occasionally a formal presentation.
Instead, there are people who are very open about sharing both what they know (which is impressive) and what they don't know (which is more important). I've never been in a group where people are more uninhibited about saying, "Wait -- I don't get it." As a result, everything we do gets enriched by some extremely good discussion.
When we don't have a formal presentation, we sometimes walk through a code project somebody's working on, or research a programming topic together (like dependency injection). Recently we've started publishing a simple programming problem and asking the members to bring a solution in their favorite language - reviewing the various solutions is a nice exercise in both language details and programming approaches.
Come see us sometime. We meet the second Wednesday of the month at 7:00 PM at the Dayton Chess Club.

One thing I find very annoying on web pages is when I click a link to open it in a new tab (middle button), and I find it was a JavaScript link and so nothing happens!
For example, go to http://ur1.ca/049e3 (it was the first one I could find but it is certainly not unique) and middle click on the screen shot of the Ubuntu Website. The desired behavior is to have that image open in a new tab. What actually happens, is that you get a blank page and no image.
This problem is down to the developers. Links with href attributes of ‘javascript:doSomething()’ are old and obsolete ways of working. With new JavaScript libraries such as jQuery, you can set a href as something completely different and still have ‘doSomething()’ run when it is clicked.
What the website mentioned above should have, is the href set to the URL of the image, so that when I middle click the link, the image opens up in a new tab, however it should have a bit of jQuery along the lines of:
$("a.image").click( function(e) {
e.preventDefault();
doSomething();
}
It isn’t that hard and it would save us all of this aggravation…

Disclaimer: If you are reading this via PlanetPlanet or a non-javascript aggregator, please visit the real page to read more
You know, we are living in a world of SOA. And even if we don’t like the new world order of the web, sometimes it can make our lifes easier.
We think that, right?
Right now I’m working on the re-implementation on my DjangoFAIed project. Which means, I’m in need of a separation between shiny new bling bling named web frontend and boring looking jsonrpc or xmlrpc for the web backend.
As you know, I’m working with Django for the daily system development, so here I’m in love with Django and RPC4Django.
The good thing about RPC4Django is that it gives me an easy way to provide two RPC types but only writing one backend.
So, having this in place, and doing some xmlrpc calls from the FAI side of life, I just need to find a way to deal with the web frontend.
So, here we are, my high rated topic: XMLHttpRequests, Javascript and Browsers, and what are they supporting.
There are at least 4 browsers I would care about:
No. 1 is my choice when developing some bling bling, No. 2 comes to my mind if I want to have a fast Javascript Execution time, No. 3 and No. 4, oh well, I use FF and Chrome even on windows, and I never had to do anything with Apple ;)
Now, let’s setup a testbed for the application. Let’s assume:
Now, I hope you have a django installation (I’m already using 1.2 beta) and installed RPC4Django. Create a new django application and add to the __init__.py file these methods:
|
1
2 3 4 5 6 |
# Create your views here.
from rpc4django import rpcmethod @rpcmethod(name="hello_world",signature=['string']) |
This is how we define a new xmlrpc/jsonrpc call which just returns “Hello World”.
Now add to your djangoproject urls.py this endpoint for our RPC calls:
(r'^RPC2/$', 'rpc4django.views.serve_rpc_request')
and add your new application and the rpc4django application to your settings.INSTALLED_APPS.
Setup your apache installation to serve your application, don’t forget your wsgi_handler.py.
Now, if we start a browser and enter “http://testrpc/RPC2/” into the location bar, you will get something like this:

(Picture taken from: David Fischer RPC4Django)
To test if our application is working just create this little xmlrpc client app:
|
1
2 3 4 5 6 |
#!/usr/bin/python
import xmlrpclib if __name__=="__main__": |
It should print out “Hello World”.
As said before, we are using jQuery as DOM library to make our lifes easier, regarding Events and Ajax things.
Let’s see how this goes:
|
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<html><head><title>testhtml</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script> <script src="json2.js"></script> <script>// < ![CDATA[ (function($){ // jsonRPC taken from http://plugins.jquery.com/project/jsonRpc (C) by <a href="http://veged.ya.ru/">Sergey Berezhnoy $.jsonRpc = $.jsonRpc || function(options) { options.type = options.type || 'GET'; var ajaxOptions = { contentType: 'application/json', dataType: options.type == 'GET' ? 'jsonp' : 'json', processData: options.type == 'GET' }; var data = { function send() { if (typeof JSON == 'undefined') { })(jQuery); |
This page includes the jQuery Script from the Google API CDN, you need to get the json2.js from http://www.json.org/
and put it in your documentroot or in your directory where the html file is saved.
When you point your browser now to this page, and you click with your mouse on “click here”, the javascript fires an click event, and inside this click event, it starts to make a Ajax Request against our rpc django app.
The result of this ajax request should be, that the content of the “<DIV> with the ID of “#testOutput will change its content and displays “Hello World”.
“Oh, but you can’t do XMLHttpRequests across different domains! It will fail, and you should know about the same origin policy !” you will say now, and you are right.
But, thanks to the “Web Applications Working Group” we have something new: CORS or simply named: Cross Origin Resource Sharing.
What is “CORS”? you will ask now. The working draft abstracts it like this:
This document defines a mechanism to enable client-side cross-origin requests. Specifications that want to enable cross-origin requests in an API they define can use the algorithms defined by this specification. If such an API is used on http://example.org resources, a resource on http://hello-world.example can opt in using the mechanism described by this specification (e.g., specifying Access-Control-Allow-Origin: http://example.org as response header), which would allow that resource to be fetched cross-origin from http://example.org.
(from: Cross-Origin Resource Sharing, W3C Working Draft 17 March 2009
This really sounds important, right? What it just says is, that now it’s possible to make Cross Site XMLHttpRequests under special cicumstancas.
What we just need to know is that Mozilla implemented this feature already in all Firefox Browsers >= 3.5.
Mozilla calls it “HTTP access control“.
Now, you will bring this example to work when you enable mod_header of your apache installation and add to your test virtualhost something like this:
|
1
2 3 4 5 6 7 |
<virtualhost *:80>
Header set Access-Control-Allow-Origin "*" DocumentRoot /whereever/that/is/ ServerName testrpc AddDefaultCharset utf-8 <some more config statements about wsgi and your django application> </some></virtualhost> |
Pay a bit of attention to the “Header” line. What it will do is easy: It will spit out a new Access-Control-Allow-Origin Header, which is set for anybody to make cross site XHR requests to your site.
It’s just like a bit when you tell Adobe Flash Crossdomain.xml to ‘allow-from-domain “*”‘. Different names, same result.
Now, restart your apache server and try the demo page again, now it should work like a charm. The contents of the div will change to “Hello World” and we are done.
Oh well, not quite done. Now we need to test this positive result in another browser, let’s choose Google Chrome.
To make a long story short, somehow this example doesn’t work, but regarding all the postings on the fantastic lazyweb, Google Chrome does support CORS!
Well, not really. It does support this feature under special circumstancas. This document tells us more.
Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers,
but they’re limited by the same origin policy.
Extensions aren’t so limited. An extension can talk to remote servers outside of its origin, as
long as it first requests cross-origin permissions.
(taken from: Google Chrome Extentions: Cross-Origin XMLHttpRequest)
There is another explanation.
Content scripts are JavaScript files that run in the context of web pages. By using the standard Document Object Model (DOM), they can read details of the web pages the browser visits, or make changes to them.
Here are some examples of what content scripts can do:
- Find unlinked URLs in web pages and convert them into hyperlinks
- Increase the font size to make text more legible
- Find and process microformat data in the DOM
However, content scripts have some limitations. They cannot:
- Use chrome.* APIs (except for parts of chrome.extension)
- Use variables or functions defined by their extension’s pages
- Use variables or functions defined by web pages or by other content scripts
- Make cross-site XMLHttpRequests
(taken from: Google Chrome Extentions: Content Scripts)
Now we have a good, fast and cool browser named Chrome, and it does not work as expected.
It should support this out of the box, and it should work like Mozillas implementation.
There are discussions in the background, regarding Greasemonkey and CORS.
Honestly, I’m writing “intranet” applications, I don’t want to use CORS in external applications. But regarding the CORS specification, I do like the way how this goes.
No need anymore to do cross site XHR via iframe (which works, but is actually painful). Furthermore, it can be a nice standard.
What we need to avoid is that really good browsers like Mozilla FF and Googles Chrome are doing what we always hated about MS: Going two different ways.
I also don’t want to write two or three different JS implementation to do the one thing. I really don’t want to support more then one browsers javascript implementation.
So, how can I get this to work without doing the old painful “iframe” way, and without writing a google extention?