JSON, Javascript, and JSONP MIME Types

A quick note about MIME types: JSON responses have a MIME type of application/json while Javascript files use application/javascript . JSONP is a JSON object within a Javascript function call, so it shares the same MIME type as Javascript ( application/javascript ).

With that said, there are some browsers (largely older browsers) and applications that don’t understand the application/json MIME type. They may require JSON responses to have a content type of application/javascript , application/x-javascript , or text/html . If you encounter issues with handling JSON, it’s a good idea to try changing the MIME type – it may solve the problem.

As a reminder, here’s how to set the content type of a response in Java (other languages have similar functions):

resp.setContentType(mime_type);

The resp object represents a javax.servlet.http.HttpServletResponse reference.

Generating Callbacks For JSONP Code

Here’s a code snippet demonstrating how to wrap JSON text within a JSONP response.

The text of the JSON object is in the string json. The variable resp represents a HttpServletResponseobject. Callback represents contents of the HTTP parameter callback , which should be set with the name of the Javascript function to call. Before calling this code, it’s a good idea to validate that parameter.

String callback = req.getParameter("callback");
String json_text = callback + "(" + json + ");";
resp.getWriter().println(json_text);

Here’s an example of a simple JSONP response:

findIP({"ip": "8.8.8.8"});

This response will call the JS function findIP (the callback parameter contents), with an object containing the property ip (the JSON data).

Access-Control-Allow-Origin In JSONP Responses

A quick note for today: JSONP responses need to include an Access-Control-Allow-Origin header set to a wildcard. If this header isn’t included, browsers won’t allow JSONP responses to be read in by Javascript.

The header key and value should look like this:

Access-Control-Allow-Origin: *

Here’s an example of this header in Java:

resp.setHeader("Access-Control-Allow-Origin", "*");

The variable resp represents a HttpServletResponse reference. Make sure to add this line before writing the body of the response to the client.

Servlet doOptions() For CORS Preflight Check

The following code sample adds a doOptions method within a servlet and sends the appropriate headers in response to a CORS preflight request.

A CORS preflight request is a HTTP OPTIONS request that most browsers send prior to making an AJAX-JSONP call. The browser expects a series of access control headers stating if the server allows cross-domain information sharing. The settings in the code below will fit the needs of the vast majority of AJAX-JSONP applications.

public void doOptions(HttpServletRequest req, HttpServletResponse resp)
        throws IOException {
    //The following are CORS headers. Max age informs the 
    //browser to keep the results of this call for 1 day.
    resp.setHeader("Access-Control-Allow-Origin", "*");
    resp.setHeader("Access-Control-Allow-Methods", "GET, POST");
    resp.setHeader("Access-Control-Allow-Headers", "Content-Type");
    resp.setHeader("Access-Control-Max-Age", "86400");
    //Tell the browser what requests we allow.
    resp.setHeader("Allow", "GET, HEAD, POST, TRACE, OPTIONS");
}

CORS Preflight Request Testing In cURL

When browsers send AJAX-JSONP requests, they often send a “preflight request” before the JSONP call. This request is a HTTP OPTIONS call asking the server whether it supports the cross origin resource sharing specification (in other words, JSONP requests).

To test a server’s support for cross origin resource sharing (CORS), you can use the cURL utility to emulate a HTTP OPTIONS request. A server that supports CORS will return a number of Access-Control headers specifying the requests it supports. Here’s an example cURL command:

curl -H "Origin: http://www.example.com" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: X-Requested-With" \
  -X OPTIONS --verbose \
  http://ip.jsontest.com/

Here’s an example of a proper CORS preflight response:

Access-Control-Allow-Origin is set to a wildcard, which means that all domains are permitted to make requests to it. Access-Control-Max-Age means that the results of this preflight request can be saved for 86,400 seconds (1 day). Access-Control-Allow-Methods means that GET and POST requests are supported.