Hack 61. Use the Right Developers Key Automatically
Hack 61 Use the Right Developer s Key Automatically
What to do when your web site lives at two domains that resolve to the same server.
Adding a Google Map to our web page [Hack #10] solved all our problems. Right? Not quite. The map works perfectly when we use http://geocoder.us, but the DNS for the Geocoder site, like that of many sites, is configured to treat http://www.geocoder.us/ as a synonym for http://geocoder.us/. The two domains resolve to the same server, which means that the same page will be served up to people asking for either domain. This works fine, until you put the Google Maps API key into the mix.
When you have the same Google Maps hack on two different URLs, even though they point to the same place, you get the message "The Google Maps API key used on this web site was registered for a different web site. You can generate a new key for this web site at http://www.google.com/apis/maps/." One can be forgiven the odd chuckle at the irony of http://maps.google.com/apis/maps/, as shown in Figure 6-21.
Figure 6-21. Getting the developer key right is a tricky thing
How does Google know what server and directory your request is coming from?
For Google Maps to work you need to include the Google Maps JavaScript library into your page as shown in this example:
A user will load your page by fetching it from your server. His web browser will then look through that page and identify images, scripts, plug-ins, and anything else that was not in the page and so needs to be loaded.
When the browser sees the script element, it attempts to load the script specified in the URL listed in the src attribute. When a browser asks for information from a web server, it also sends information, including the name of the server and the page that referred the user to get the script. Google Maps is probably using the HTTP referer that is automatically sent to the server by your browser.
There are two general ways to solve this problem. Either you maintain more than one developer key and somehow pick the right one to use when you load the Google Maps library, or you force people to always use the URL that is associated with your developer key by silently fixing bad URLs.
6.12.1. Pick the Right Key in Perl
If you generate the page from a script, such as with PHP, Python, or Perl, you can maintain a list of server names and directories and the matching developer keys and then dynamically generate the script element to load the Google Maps library. This is a Perl example that sets the correct developer's key based on the HTTP_HOST that was used to call the script. I've shortened the developer's keys and replaced the actual domain names with placeholders.
#!/usr/bin/perl # These are the keys for www.testingrange.com/pix, www.chilidog.com/pix, and www.journalsonline.com/pix my $key_tr = "ABQIAAAAJhHGNa8WG19AE1v8p0OkZxQpjl…4EDQ"; my $key_jo = "ABQIAAAAJhHGNa8WG19AE1v8p0OkZxSB9G…nOFw"; my $key_cd = "ABQIAAAAJhHGNa8WG19AE1v8p0OkZxQCuE…rtNA"; # which server are we? my $http_host = $ENV{HTTP_HOST}; my $key = ''; # set the key to match the host $key = $key_tr if ($http_host =~ /first-domain/); $key = $key_jo if ($http_host =~ /second-domain/); $key = $key_cd if ($http_host =~ /third-domain/); print "Content-type: text/html "; print qq(
<-->);
This script sets variables for the developer keys for each of our domains, then sets the variable $key to one of those values depending on the host-name that was used to call this script. If we have first-domain.com, second-domain.com, and third-domain.com all pointing to the same web page, then this script will set the correct developer's key.
In real life, I would use a template. In this example, the Hello World map is in the script and is printed out with the print qq( ) command. The qq( ) operator in Perl automatically does variable interpolation, which means the variable $key will be replaced with the correct developer's key.
<-->
This example assumes completely different server names. The more common case is to have http://www.mydomain.com and http://mydomain.com both work. Assuming you've set the keys correctly, these lines will do that.
$key = $key_plain if ($http_host !~ /^www/); $key = $key_www if ($http_host =~ /www/);
These lines say to use the value of $key_plain if the HTTP_HOST does not start with www, and use the value of $key_www if the host does start with www. The important point is to use the right key. If you have scripts in different directories, you'll want to take a look at the variables $ENV{SCRIPT_NAME} and $ENV{REQUEST_URI}. These variables contain the full path and page. You'll need to strip off the page name so you can compare the host and directory. There is more than one way to do it!
6.12.2. Use JavaScript to Accomplish the Same Goal
You can get the same effect dynamically with JavaScript. This is the Hello World map with a bit of JavaScript that looks to its own href to determine which URL it was loaded as, and then loads the map library by dynamically selecting the right developer's key. In this example, I've shortened the full developer's keys because you can't use my keys, and they are just too ugly to be printed in a book.
Which server is this?
The difference from the original Hello World is the script block in the header. It defines variables for the different developer's keys, and then picks the right key based on the current URL, which is available to JavaScript in the variable window.location.href. There is a lot in common between the JavaScript and Perl approaches. They both pick from a set of developer's keys. The next approach lets you use a single key, but it changes the URL that the user sees.
6.12.3. Using Apache's mod_rewrite to Share Keys
If you are using the Apache web server you may be able to use the mod_rewrite module to quietly fix your URLs so that they match your developer key. In this example, we will use mod_rewrite to silently add www. to the front of any calls to http://mappinghacks.com. This technique assumes that your Apache is set up to allow .htaccess to override the FileInfo setting.
Apache has a lot of options, including options that can be set on per directory basis. The most common way to set them is the Apache configuration file (often /etc/httpd/conf/httpd.conf) or in a file called .htaccess in the directory where you keep your web pages.
The .htaccess file will only work if the Apache configuration file is set up to allow it to work. In your httpd.conf file, there will be at least one section. Note that Apache configuration is Byzantine in its complexity, so forgive my simplifications. There needs to be a line in the section that starts with AllowOverride and specifies either All, which means the .htaccess file can control all aspects of Apache's access to that directory, or FileInfo, which allows the .htaccess file to control file things, including use of the mod_rewrite module.
6.12.4. Edit .htaccess to Rewrite Requests
I generated a key for http://www.mappinghacks.com/projects/gmaps. But I'd like people to be able to use http://mappinghacks.com/projects/gmaps as well. Here is an example of a mod_rewrite rule that will redirect requests from http://mappinghacks.com/projects/gmaps to http://www.mappinghacks.com/projects/gmaps. Create a new .htaccess file, or edit the existing one, to add these three lines.
RewriteEngine on RewriteCond "%{HTTP_HOST}" "!^www" [NC] RewriteRule "(.*)" "http://www.%{HTTP_HOST}%{REQUEST_URI}"
The first line turns on mod_rewrite. The second line looks at the HTTP_HOST field, which should be the server name from the URI, mappinghacks.com or www.mappinghacks.com. It does a regular expression match against the pattern !^www. Bang (!) means negation, or not, the caret (^) means to match at the start of the string, and [NC] says to ignore case (i.e., No Case). The RewriteRule tells Apache what to do if the Rewrite Condition is met. So this says "if the HTTP host doesn't start with www replace the whole URI with http://www. plus the HTTP host, plus the filename, and any parameters that were originally passed." To make it simpler, it just says "make sure the URL starts with www."
6.12.5. See Also
- Apache URL Rewriting Guides:
- Apache Version 1.3: http://httpd.apache.org/docs/1.3/misc/rewriteguide.html
- Apache Version 2.0: http://httpd.apache.org/docs/2.0/misc/rewriteguide.html
These are almost conversational guides to mod_rewrite. From the 2.0 version: "With mod_rewrite you either shoot yourself in the foot the first time and never use it again or love it for the rest of your life because of its power."