Category Archives: JavaScript

JSONP: How Does it Work?

Interestingly enough, I’ve seen a few candidates in interviews the last few months flail a bit when asked about getting around the same origin policy using JavaScript in a browser. Most know enough to toss out the term “JSONP” and perhaps another solution (e.g. proxy or CORS) but can’t really explain why one might prefer a certain solution over another. In fact, few could even describe how JSONP works aside from some JQuery library they always “just include”.

What is JSONP?

If you spend some time thinking about how JavaScript operates in a browser, you will probably arrive at the realization that the policy does not seem to effect script tags. Specifically, how many of us get JQuery from the Google CDN or some other source that is not the same origin as our current page? (I hope that answer is “most”, by the way.)

That same logic, combined with some DOM knowledge, would probably lead you to experiment with loading other types of JavaScript, aside from a library, using script tags. Since JavaScript has a global scope, if you were to reference a function that could handle that data you could then link it with your application and do something interesting with it.

JSONP is born.

The idea of JSONP is actually pretty simple: toss a script tag into the DOM with a reference to a resource that returns JSON data. Have the server return said JSON with “padding” (the “P” part of JSONP) that executes a function wrapping the incoming data. In order for this to work properly, the server API must also support JSONP. Typically, the function name is named as the callback parameter. For example, let’s pretend you are accessing a service that returns JSON weather information that looks like:

http://www.weather.com/90210

Which returns JSON like:

{"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"}

Adding JSONP support would result in a URL that looks like:

http://www.weather.com/90210?callback=MyCallback

And returns:

MyCallback({"zipCode": "90210","location": "Beverly Hills","high": "85 degrees","low": "55 degrees"});

This data is now exposed to the rest of the application as long as MyCallback is a valid function name in the global scope.

Most JSONP implementations in libraries like JQuery will automatically generate callback functions as well as cleaning up inserted script tags when the callback executes, but the basic idea is actually pretty simple.

Why To Use JSONP?

JSONP is universally supported on just about every browser and a lot of useful APIs have support for it already in place (Yahoo, Twitter, Google, etc.) Aside from the regular XMLHttpRequest and DOM differences, nothing really special needs to be done to make it work across different browsers. Finally, since it has been around for a bit, there are pretty mature JSONP plugins for just about every major library and framework around (JQuery, YUI, Prototype, etc.)

Why NOT To Use JSONP?

Deciding against using JSONP is directly related to how it works. First of all, the only HTTP method you can use is GET since that is the only method script tags support. This immediately eliminates the use of JSONP as an option to interact with nice RESTful APIs that use other HTTP verbs to do fun stuff like CRUD. And while we’re on the subject of GET, note that using anything other than URL parameters to communicate with the server API (e.g. sending some JSON over) is also not possible. (You could encode JSON as a URL parameter, but shame on you for even thinking that.)

Secondly, since you are relying on a script tag, there is no uniform way to catch errors. Some browsers will allow attaching a callback to the script tag (e.g. onError() {}), but it is not universally supported (any guesses on which browsers don’t support it?) and therefore can’t be relied upon without some unfortunate hacks. If the called API is doing syntactically correct things like returning an HTTP 404 response code when a resource cannot be found, there is no way to easily catch that error condition or parse the response body for further information. Instead, what typically takes place are APIs that return HTTP 200 status codes but contain JSON describing an error condition. There are worse things in the world, but I cringe at that approach these days.

Finally, keep in mind that JSONP is really a security vulnerability. It happens to be an extremely useful one, but the same origin policy does provide value in protecting the application and using JSONP is willfully opening up a hole that could potentially become an attack vector.

What Are Some Alternatives?

The easiest alternative is setting up a proxy to an external API through the same origin as the web application. This can be done pretty easily using tooling built into web servers like Apache and Nginx.

If you are able to remove support for IE7 and don’t care much about Opera, the end game is Cross-Origin Resource Sharing (CORS). This solution allows the full array of HTTP verbs and errors (including POSTing JSON) and has a greater level of security than JSONP. It has decent support on IE8+ (with some provisos) and is relatively easy to implement on the server. The downside is that many popular public JSON APIs today don’t yet support it.

Conclusion

CORS >= Proxy > JSONP (most of the time).

Advertisements

See Dart … Java?

About a month ago, Google made headlines when an email describing ambitious plans to re-create JavaScript was leaked to the web. This email created quite a stir and spawned numerous debates ranging from the hubris of Google in trying to single-handedly replace such a ubiquitous staple of the web to the possible merits of Google’s decision on a technical level and the kinds of exciting innovations that could occur.

While I personally didn’t feel great about Google’s actions, I decided to reserve my public judgement for the time when Google actually released the language. Two days ago, that finally happened. So, let’s take a look:

main() {
  print('Hello, Dart!');
}

Ummm … ok. This chunk of code looks similar to JavaScript, so that’s not all bad. However, I was really expecting something more groundbreaking in terms of syntax. While I don’t loath semi-colons as line endings (you have to have something, right?) the new trend these days is to exclude them. Specifically coming from a JVM perspective Scala, Groovy and Clojure, three of the most popular Java alternatives, are happily semi-colonless. Also, as Google has deep Python roots, I expected they’d create something with a more “modern” syntax. But that’s ok … I can live with semi-colons. Let’s dig a bit through the Dart sample source code (can currently be found on Dart’s Google code page).

Check out https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/client/samples/swarm/BiIterator.dart (I’ve removed the comments for brevity):

class BiIterator<E> {
  ObservableValue<int> currentIndex;

  List<E> list;

  BiIterator(this.list, [List<ChangeListener> oldListeners = null]): currentIndex = new ObservableValue<int>(0) {
    if (oldListeners != null) {
      currentIndex.listeners = oldListeners;
    }
  }
  E next() {
    if (currentIndex.value < list.length - 1) {
      currentIndex.value += 1;
    }
    return list[currentIndex.value];
  }

  E get current() {
    return list[currentIndex.value];
  }

  E previous() {
    if (currentIndex.value > 0) {
      currentIndex.value -= 1;
    }
    return list[currentIndex.value];
  }

  void jumpToValue(E val) {
    for (int i = 0; i < list.length; i++) {
      if (list[i] === val) {
        currentIndex.value = i;
        break;
      }
    }
  }
}

When I first saw this code, I instantly recognized a very similar syntax to Java 5 generics. Eerily similar, in fact. As powerful as Java generics are, not too many people like the syntax. To port what many consider to be kruft to a brand new language is an odd choice.

Another interesting thing about this code is the inclusion of strict comparison operators (i.e. ‘===’ and ‘!==’, see line 31 for an example). While the use of these operators is instantly recognizable to those of us who regularly use JavaScript, I think it a very odd decision to include these operators in a brand new language. They are, essentially, a JavaScript oddity that often confuses people when they first learn the language.

So far, things aren’t looking great for Dart.

There is hope, however: Dart has great support for concurrency. It implements a version of the Actor model (see http://www.replicator.org/content/a-first-look-at-dart-the-programming-language for details) placing code into Web Workers behind the abstraction. Concurrency is rarely easy and the Actor model is a great way to abstract that kind of complexity away from the developer.

So, let’s take a look at a basic Actor (Dart’s interface is called an Isolate):

class Printer extends Isolate {
  main() {
    port.receive((message, replyTo) {
      if (message == null) port.close();
      else print(message);
    });
  }
}

main() {
  new Printer().spawn().then((port) {
    for (var message in ['Hello', 'from', 'other', 'isolate']) {
      port.send(message);  
    }
    port.send(null);
  });

Huh. It doesn’t look terrible, but I’ve been doing a lot of Scala development recently and Scala also happens to have actors. Let’s take a quick look at how Scala might implement the above code:

import scala.actors.Actor._ 
val portActor = actor {
    while (true) {
        receive {
            case msg => println(msg)
        }
    }
}
List("Hello", "from", "other", "actor").foreach( word => portActor ! word)

Granted: these are both contrived examples. However, look at the Scala version. It’s doing some tricks like importing a static Actor but it is still, at least to my eyes, much more readable and elegant than the Dart version. While it’s nice to have an actor-based model for client development, I feel like Dart’s falls short in comparison to Scala’s state of the art implementation. Again, considering this is a brand new language, this is puzzling.

Finally, Dart itself can either be executed in a virtual machine or transpiled to JavaScript for execution in a browser. Since most browsers outside of Chrome won’t have much support for a native Dart VM in the near future, let’s take a look at Dart’s transpiling overhead. This is probably all you need: https://gist.github.com/1277224. Dart’s ‘Hello World’ application transpiled to over 17,000 lines of JavaScript. Wow. To be fair, this overhead has to do with setting up Dart’s optional typing system and other niceties of the language which is more akin to including a library. As such, this isn’t an apples-to-apples comparison with JavaScript itself or something like CoffeeScript which transpiles in a more one-to-one fashion.

But still. Wow.

So, at least for now, it seems like Dart is a bit of a snooze. As much as I was disappointed in Google with not being more open about the development of Dart, I was also excited in seeing something that would simply blow away JavaScript and set the stage for something ground-breaking (maybe something like “ScalaScript”). Dart is not that. Core Java developers will likely feel right at home with Dart, but I can’t see the huge community of client-side JavaScript engineers being very excited about this.

Dart, I am disappoint.