Mar 21 2009
Cross-posted from the Particls blog.
“IE6 is the new Netscape 4. The hacks needed to support IE6 are increasingly viewed as excess freight. Like Netscape 4 in 2000, IE6 is perceived to be holding back the web.”Jeff Zeldman, standards guru
I saw the link to the bring down IE 6 site today via our friends on Twitter and simply had to announce our support for such an initiative. IE6 while once the browser to which all others were bench marked, is now, frankly the bane of an Internet Start up’s existence. It might have been great once, but all good things must come to an end, and for IE6, that time is now.
For Faraday Media, IE6 support has never been a priority, since our users and visitors are overwhelmingly Firefox users, so unofficially, we’d already been on this bandwagon. Today, it’s official.
If you’re chained to IE6 due to some corporate SOE policy, you have my sympathy. If you’re using IE6 voluntarily, then you only have yourself to blame (just for you, here is the link to Firefox).
I really encourage other start-ups to stand-up and vocally (and officially) join the movement.
Mar 18 2009
I do a lot of web development in Visual Studio 2005 (and 2008) on a Vista workstation joined to a domain. Up until recently I've been working on a very large set of RESTful APIs written in a special library for creating RESTful APIs using metaprogramming. Its a great in-house library, but its not compatible with IIS7 - and debugging the PHP requests through the production compiled staging server (aka trawling through many many large log files) is become tedious and difficult.
I thought, wouldnt it be useful if I could debug the APIs if the guys could use the APIs hosted on my machine by the ASP.NET Development Webserver. But alas, remote connections are not allowed to this light-weight web server making this impossible.
Or is it?
I have been wanting to learn more about reverse proxies as I know from buzz in the industry that they can be god sends. I thought, that's what I need! A reverse proxy to forward external web requests into "internal requests" to trick the ASP.NET Development Webserver that the request was local, when in fact it isn't. After playing with a number of options, it turned out that what I had initially avoided for fear of it being too difficult was actually the best and easiest. Squid! For those not familiar with the concept of reverse proxies, I thought I'd paste this snippet from the Squid wiki:
What is the Reverse Proxy (httpd-accelerator) mode?
Occasionally people have trouble understanding accelerators and proxy caches, usually resulting from mixed up interpretations of "incoming" and "outgoing" data. I think in terms of requests (i.e., an outgoing request is from the local site out to the big bad Internet). The data received in reply is incoming, of course. Others think in the opposite sense of "a request for incoming data".
An accelerator caches incoming requests for outgoing data (i.e., that which you publish to the world). It takes load away from your HTTP server and internal network. You move the server away from port 80 (or whatever your published port is), and substitute the accelerator, which then pulls the HTTP data from the "real" HTTP server (only the accelerator needs to know where the real server is). The outside world sees no difference (apart from an increase in speed, with luck).
Quite apart from taking the load of a site's normal web server, accelerators can also sit outside firewalls or other network bottlenecks and talk to HTTP servers inside, reducing traffic across the bottleneck and simplifying the configuration. Two or more accelerators communicating via ICP can increase the speed and resilience of a web service to any single failure.
The Squid redirector can make one accelerator act as a single front-end for multiple servers. If you need to move parts of your filesystem from one server to another, or if separately administered HTTP servers should logically appear under a single URL hierarchy, the accelerator makes the right thing happen.
Start by obtaining a binary release of Squid. I'll be using the latest stable release, standard 2.7.STABLE4. Squid does not require installation as such, simply unzip it where you wish. To make it simple, I'll install Squid directly in C:\squid as the standard Squid configuration expects it to be installed here - it's easy to change though!
We'll start by installing Squid as a service, before doing the actual configuration. Open a command prompt and go to C:\squid\sbin. Now run "squid -i -n Squid". This will install Squid as a service under the name "Squid".
C:\squid\sbin>squid -i 0n Squid Registry stored HKLM\SOFTWARE\GNU\Squid\2.6\Squid\ConfigFile value c:/squid/etc/ squid.conf Squid Cache version 2.7.STABLE6 for i686-pc-winnt installed successfully as Squid Windows System Service. To run, start it from the Services Applet of Control Panel. Don't forget to edit squid.conf before starting it.
Before we start Squid, we have to configure it. Go to C:\squid\etc and make a copy of squid.conf.default and call it squid.conf. Do the same for mime.conf.default (we won't edit this one, but it's needed). There are hundreds of configuration options, all very well documented. Now, I won't go over all the options, so simply by-pass the entire contents of the squid.conf file, we'll add only the configuration options that we need at the bottom.
http_port 8880 accel defaultsite=your.dns.address cache_peer localhost parent 9977 0 no-query originserver name=myAccel acl our_sites dstdomain your.dns.address http_access allow our_sites cache_peer_access myAccel allow our_sites cache_peer_access myAccel deny all
This particular reverse proxy is going to co-exist on the same machine that is hosting the website, but for better load balancing, you should make the first line http_port 80, and the cache_peer line, change localhost to the ip of the webserver and parent 9977 to 80 as well. This way, when the Squid server gets a request on port 80 (the default HTTP port) it will properly reverse-proxy to the default webserver port on the web server machine. The other options are handy to know, so have a read, but so long as your firewall has the relevant ports open, the config file as it stands is all you need at a minimum to get things going. Another handy thing to know (as your site grows) is that the reverse-proxy capabilities of Squid are quite advanced. To load balance requests among a set of backend servers allow requests to be forwarded to more than one cache_peer, and use one of the load balancing options in the cache_peer lines. I.e. the round-robin option:
cache_peer ip.of.server1 parent 80 0 no-query originserver round-robin cache_peer ip.of.server2 parent 80 0 no-query originserver round-robin
This is very asy to spread load of your websites and services. Wikimedia is quoted a while ago as saying that their front-end squid servers have a 75% hit rate, effectively quadrupling the load capacity of their Apache servers. No doubt their configuration is quite different to this example, but it gives you an idea of just how much benefit a Squid based reverse proxy can be.
Before you run off and start the Squid service, first run "squid -z" which will report any configuration errors in your conf file. If all went good, it should look something like:
C:\squid\sbin>squid -z 2009/03/18 11:35:06| Creating Swap Directories
Since its working great, just execute "net start Squid" and:
C:\squid\sbin>net start Squid The Squid service is starting. The Squid service was started successfully.
BAM! Your fung foo is strong. Simply test the external url and it should forward the request and response back for you.
I know this has worked wonders for me, I hope you have the same positive experience.
Mar 17 2009
Unable to start debugging on the web server. Debugging failed because integrated Windows authentication is not enabled
Recently, I was trying to get a .Net 2.0 web application I am working on, running from IIS 7 under my Vista Ultimate workstation so it could be remotely debugged. I went and changed the appropriate project settings, but when ran the web app, it said:
Error while trying to run project: Unable to start debugging on the
web server. Debugging failed because integrated Windows authentication
is not enabled.
After some poking arround in IIS 7, which I am quite unfamiliar with, I found a very easy solution.
- Right-click on "My Computer" and select "Manage"
- Under "Services and Appliccations" select "Internet Information Services"
- Find the appropriate website (probably called "Default Web Site")
- Find the icon named "Authentication" and double-click it.
- Make sure "Windows Authentication" is in the list, and enable it.
Your Visual Studio should now works as advertised.
Mar 14 2009
Quite a while ago, in the absence of any alternatives, we built a remote deployment utility so we could push updates to our staging and production servers without manual intervention.
Recently however, while deploying the latest code for an internal project to a new production server, the .Net 2.0 automatic deployment I had created threw the following, rather unfriendly error:
Exception Details: System.ComponentModel.Win32Exception: The logon attempt failed [Win32Exception (0x80004005): The logon attempt failed] [InvalidCredentialException: The server has rejected the client credentials.]
In order to protect the server from attack we have a system service which we communicate to using .Net remoting, which requires authentication.
Apparently the bug occurred, because I created the user account which we authenticate against on the new server, after I have installed the system service.
I uninstalled the system service, reinstalled it and it magically worked like it should.
Mar 14 2009
Production level servers can be tricky. Mostly because of the inherent, increased security needed to protect online (and exposed?) assets. Our Postgres server is one such asset.
But opening the necessary ports to allow access to the database server (for maintenance) can expose the server to possible attack. Fortunately, if your Postgres server is on a UNIX or Linux based machine with SSH installed, you can forward the Postgres port through the SSH tunnel.
- ssh -L 1234:localhost:5432 email@example.com
In PGAdmin, simply connect to localhost:1234, and you will connect to the production server through the SSH connection without the need to open a port on the external firewall.
Mar 2 2009
If you want to match approximate strings with fuzzy logic, use the Levenshtein distance algorithm. Many projects need this logic, including programs such as spell-checkers, suggestion searches and plagiarism detectors.
In information theory and computer science, the Levenshtein distance is a metric for measuring the amount of difference between two sequences (i.e., the so called edit distance). The Levenshtein distance between two strings is given by the minimum number of operations needed to transform one string into the other, where an operation is an insertion, deletion, or substitution of a single character. A generalization of the Levenshtein distance (Damerau–Levenshtein distance) allows the transposition of two characters as an operation.
I needed to simply to measure the difference between two independant strings. This was my saving grace, and the C# implementation I found:
- using System;
- /// <summary>
- /// Contains approximate string matching
- /// </summary>
- static class LevenshteinDistance
- /// <summary>
- /// Compute the distance between two strings.
- /// </summary>
- /// <param name="s">The first of the two strings.</param>
- /// <param name="t">The second of the two strings.</param>
- /// <returns>The Levenshtein cost.</returns>
- public static int Compute(string s, string t)
- int n = s.Length;
- int m = t.Length;
- int[,] d = new int[n + 1, m + 1];
- // Step 1
- if (n == 0)
- return m;
- if (m == 0)
- return n;
- // Step 2
- for (int i = 0; i <= n; d[i, 0] = i++)
- for (int j = 0; j <= m; d[0, j] = j++)
- // Step 3
- for (int i = 1; i <= n; i++)
- //Step 4
- for (int j = 1; j <= m; j++)
- // Step 5
- int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
- // Step 6
- d[i, j] = Math.Min(
- Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
- d[i - 1, j - 1] + cost);
- // Step 7
- return d[n, m];