Porting JavaScript to Internet Explorer

While porting a small AJAX application I wrote to Internet Explorer, I encountered a few problems:

  1. IE doesn’t like <script> tags without a matching closing tag. This is especially a problem if you use the src attribute and try to use an XHTML-like closing tag like this:
    <script src="..."/>
    

    In this case IE doesn’t draw anything at all, since it keeps looking for the end of the script and doesn’t find it. This is especially a problem with templating toolskits like Kid. If Kid encounters a construct like <foo></foo> it will correctly shrink this to <foo/> in the XML output. The solution is rather easy: Insert a newline character between openening and closing tag in the template. Since Kid has now way to determine whether this whitespace is significant it will keep it in the output.

  2. It seems that IE doesn’t like trailing commas in JavaScript object literals:
    var o = {
        x: 'Foo',
        y: 1,
    };
    

    I like to insert trailing commas in cases like this. It’s easy to forget to add one if extending the property list. Firefox parses the trailing comma, while IE doesn’t. (IE follows the ECMAScript standard here, which doesn’t allow the trailing comma. Indeed in array literals a trailing comma has a special meaning, so it’s probably a good idea to disallow the trailing comma in object literals.)

  3. My AJAX application queries a web service for a list of items and displays that list in a table. The table is generated in HTML code like this:
    <table id="mytable">
        <tr>...</tr>
    </table>
    

    I then used JavaScript code like the following to populate that table:

    var table = document.getElementById("mytable");
    var trTag = createRow();
    table.appendChild(trTag);
    

    This worked fine in Firefox, but no matter what I did, IE refused to render the table rows. After much hair tearing I remembered that Firefox’s DOM Inspector showed a TBODY element just beneath the TABLE element and TR elements are attached to the former. The DOM Inspector basically showed the following structure:

    • TABLE id=mytable
      • TBODY
        • TR (my header row from the HTML)
      • TR (a dynamically generated row)

    So I changed my code to append the newly generated rows to the TBODY instead:

    var table = document.getElementById("mytable").
        getElementsByTagName("tbody")[0];
    var trTag = createRow();
    table.appendChild(trTag);
    

    This works in Firefox and IE.

Apache, cgi-bins, and the Authorization header

I had a problem: Server A runs a web service, which requires users to authenticate using the standard HTTP authentication mechanism. Server B should have web pages that use AJAX to query A’s web services. Server B’s web pages also require authentication, using the same scheme, backend and database as server A. There are two problems:

  1. JavaScript web pages can only access web services/pages on the same server using XMLHttpRequest, for security reasons. Solution: Use a forwarding/proxy service. E.g. to access http://a.example.com/service from b.example.com add a service http://b.example.com/servicethat just forwards requests to the web service on A. This solution is quite straight forward.
  2. Since B uses the same authentication scheme as A we need to forward authentication information passed to B’s forwarding service on to A. Unfortunately this is not straight-forward, since the Apache HTTP Server provides no easy way to read the full authentication information passed to it via a cgi-bin. The only available information is the REMOTE_USER environment variable. This is not enough to construct a new Authenticationheader, though, since password information is stored encrypted in the account database.Finally I found a solution in the Zope 2 documentation. Apache’s mod_rewrite comes to the rescue. It allows you to read arbitrary HTTP headers and add arbitrary environment variables before executing a cgi-bin. The following recipe added to the appropriate .htaccess file adds a HTTP_AUTHORIZATION variable:
    RewriteEngine on
    RewriteBase /
    RewriteCond %{HTTP:Authorization}  ^(.*)
    RewriteRule ^(.*)$ $1 [e=HTTP_AUTHORIZATION:%1]