Monday, November 9, 2009

JSONP and Google Maps API Geocoder - Not a Bug

This post is about a sudden stop of a functionnality in the Google Maps Geocoding API. Some people thought they dropped support for JSONP but they only changed it.

Edit: Don't forget to read comments of this post, someone raised a point that is somewhat questioning the validity of the article. In other words, you can still harvest Google's data simply by using the API. But it appears that Google have somewhat made it more difficult to use the service when bypassing the official API with JSONP for example. I think the real intention is to prevent the use of the service with other libraries and widgets like jQuery plugins for instance.

Edit: I have a fix for you if you experience a JSONP problem with jQuery and the Google Maps API services. I believe that they just don't want you to use it with other libraries than their own.

Introduction


Hi,

Remember the 400 bad request error you are receiving when using the Geocoder with JSONP? Well this behavior is by design (like Microsoft like to call it). It appears that Google now forbids the use of the library beyond the public interface documented. A Google representative told me that the callback parameter was never supported... well officially I guess, because we were able to use JSONP before on the library (and we all know that both parties have to implement it for JSONP to work).

The "bug"


Anyway! I have my own idea on the why you can't do it anymore and I understand Google for doing so. There is a 15,000 requests limit per 24 hours for a single IP to prevent abuse and data mining on the library. When you use the library with JSONP calls, the requests are spread across the visitors and doesn't account on the server's IP! It is unlikely that a visitor will do 15,000 geocoding requests and get himself blocked from Google. But a web server, it is.

clients are geocoding directly with google through JSONP

So what's the problem? The server only offloads its requests to the visitors! For a legitimate website okay, but a malicious web server could take advantage of this architecture. For example, each visitors could be used to do data mining on behalf of the web server. I think this is what Google is trying to prevent. Remember, each of the client can potentially do 15,000 request per 24h and nothing prevents those requests to be forwarded back to the web server:

the requests made by the clients can be retrieved by the server

But this technique doesn't work anymore... back to square one (I mean, back to square one for the white hats). The solution, if you were using JSONP like me, is to create a proxy on your web server. The proxy is a simple page that forwards requests from your clients to Google and sends back the response from Google to your clients. We're doing plain old JSON calls :) The negative impact is that all the requests are made by your web server's IP. That's exactly what Google wanted to fix (At least, in my opinion. Remember, this post is entirely based on my intuition). Here's how it works:

the server do all requests to Google for its clients

Now, your next question may be "how many requests my server can potentially do to satisfy my clients?". Let's see: 15,000 / 24 / 60 ~ 10 requests per minute. That's not a lot considering the traffic your web server may have.

Conclusion


So now you know that the "bug" wasn't a bug. I hope you will be able to come up with an alternate solution for you web site. As you saw, you always have the proxy technique.

I'm putting time and effort on this blog and having you here is my reward. Make me feel better and better everyday by spreading the love with the buttons below! Also, don't hesitate to leave a comment. Thanks for reading!

Related Articles



See ya

4 comments:

deathbytweet said...

Hi Mike - great post! We had the same problem, and I came to the same solution yesterday. Only then did I realize I that the script I was refactoring was actually part of a widget that could be plugged into any number of sites - which meant that I couldn't use (standard JSON plus) a local proxy. So instead I set up a proxy on the widget's originating server which then calls the Google API, wraps it in a JSONP callback and passes that back to the widget's javascript. It's convoluted, but it works.

Your inferred rationale for google's change of policy makes perfect sense.

Weird thing is, we found that if we preceded our original gmap call with jQuery.ajaxSettings.cache = true; the JSONP call continued to work. This is clearly something of a hack, and we realized we couldn't rely on it, so we refactored accordingly. Weird though.

Mike said...

JSONP must be implemented on both ends. If they want to block it completely, they should remove the "func && func({...})" part in their response.

But, doing that would probably break something in their libraries since the Maps/Geo API must be able to Goecode adresses (Like when you're asking for driving directions)

I think they didn't block it completely, but a little bit to limit abuse. Or they simply changed something in their libraries causing that side effect! Who knows...

Anonymous Avatar Anonymous said...

I don't understand the problem. Why don't you use the gclientgeocoder function ? As described in the terms, you have a limitation of 15.000/ip (javascript client side). This should be enough and should solve the problem with the webserver ip limitation.

Mike said...

You're absolutely right.

But as deathbytweet said, most of the libraries and widgets are taking URLs as parameter when doing ajax calls.

Using the GClientGeocoder would transfer the workload from the public libraries to yours...

But the problem is that public libraries might not expose an interface to pass already downloaded data to their ajax widget/tools/objects.

But still, you made me realize how easy it is to do Geocoding with the Google Maps API!

Thank you

©2009-2011 Mike Gleason jr Couturier All Rights Reserved