How to Generate a JSONP Response
This article provides a script policy that will generate a JSONP response on demand. It is driven by two things:
- The Accept Header—if Accept is set to application/javascript, this will generate JSONP.
- The JSONP query param—if there is a JSONP query param present, this script uses the param value as the wrapping function name. If not, it defaults to jsonFunction.
There are a few subtleties in this script.
-
It has to use information that is only available on the request, in the response processing, so it extracts these things (the accept header and the JSONP param) during request message processing and stores them in the exchange.
-
If the returned content isn't already JSON, it mediates it to JSON by normalizing it to XML and then serializing it.
-
If the returned content is already application/javascript the script doesn't do anything.
To make this work, you simply need to create an operational script policy using the following self-contained script, and then attach this policy to your virtual service.
// Get the message and the exchange var msg = messageContext.getMessage(); var exg = messageContext.getExchange(); // Are we dealing with a request, response or fault switch(messageContext.getParameterType()) { case 0: auditLog.debug("Request Message"); // Get the Accept header and store it in the exchange var accept = String(msg.getTransportHeaders().get("Accept").getValue()); exg.setProperty("accept.header", accept); // See if there is a JSONP query param var queryString = String(msg.getProperty("com.soa.message.TRANSPORT_QUERY")); var jsonpFunction = queryString.match(/jsonp=([^\&]*)/im); if (! jsonpFunction) { jsonpFunction = ["empty", "jsonpFunction"]; } // store the JSONP function name in the exchange exg.setProperty("jsonp.function", jsonpFunction[1]); break; case 1: auditLog.debug("Response Message"); // Get the Accept Header from the exchange var accept = exg.getProperty("accept.header"); // If the header is looking for application/javascript then we will mediate if (accept == "application/javascript") { // if we don't already have JavaScript content if (msg.getContentType() != "application/javascript") { // make sure we have JSON if (msg.getContentType() != "application/json") { var content = msg.normalize(); var jsonContent = serializer.read(content.getContentAsString()); msg.setStringContent(jsonContent); } // Wrap the JSON result in the JSONP function name var jsonpContent = exg.getProperty("jsonp.function") + "(" + msg.getContentAsString() + ");"; msg.setStringContent(jsonpContent); msg.setContentType("application/javascript"); } } break; default: auditLog.debug("Fault"); }
Happy JSONP Generation.