@qooxdoo/framework
Version:
The JS Framework for Coders
168 lines (139 loc) • 4.56 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2013 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Richard Sternagel (rsternagel)
************************************************************************ */
/**
* Parsers for parsing response strings (especially for XHR).
*
* Known parsers are: <code>"json"</code> and <code>"xml"</code>.
*
* @require(qx.util.ResponseParser#parse)
*/
qx.Bootstrap.define("qx.util.ResponseParser",
{
/**
* @param parser {String|Function} See {@link #setParser}.
*/
construct: function(parser) {
if (parser !== undefined) {
this.setParser(parser);
}
},
statics:
{
/**
* @type {Map} Map of parser functions. Parsers defined here can be
* referenced symbolically, e.g. with {@link #setParser}.
*
* Known parsers are: <code>"json"</code> and <code>"xml"</code>.
*/
PARSER: {
json: qx.lang.Json.parse,
xml: qx.xml.Document.fromString
}
},
members :
{
__parser: null,
/**
* Returns given response parsed with parser
* determined by {@link #_getParser}.
*
* @param response {String} response (e.g JSON/XML string)
* @param contentType {String} contentType (e.g. 'application/json')
* @return {String|Object} The parsed response of the request.
*/
parse: function(response, contentType) {
var parser = this._getParser(contentType);
if (typeof parser === "function") {
if (response !== "") {
return parser.call(this, response);
}
}
return response;
},
/**
* Set parser used to parse response once request has
* completed successfully.
*
* Usually, the parser is correctly inferred from the
* content type of the response. This method allows to force the
* parser being used, e.g. if the content type returned from
* the backend is wrong or the response needs special parsing.
*
* Parser most typically used can be referenced symbolically.
* To cover edge cases, a function can be given. When parsing
* the response, this function is called with the raw response as
* first argument.
*
* @param parser {String|Function}
*
* Can be:
*
* <ul>
* <li>A parser defined in {@link qx.util.ResponseParser#PARSER},
* referenced by string.</li>
* <li>The function to invoke.
* Receives the raw response as argument.</li>
* </ul>
*
* @return {Function} The parser function
*/
setParser: function(parser) {
// Symbolically given known parser
if (typeof qx.util.ResponseParser.PARSER[parser] === "function") {
return this.__parser = qx.util.ResponseParser.PARSER[parser];
}
// If parser is not a symbol, it must be a function
if (qx.core.Environment.get("qx.debug")) {
qx.core.Assert.assertFunction(parser);
}
return this.__parser = parser;
},
/**
* Gets the parser.
*
* If not defined explicitly using {@link #setParser},
* the parser is inferred from the content type.
*
* Override this method to extend the list of content types
* being handled.
*
* @param contentType {String}
* @return {Function|null} The parser function or <code>null</code> if the
* content type is undetermined.
*
*/
_getParser: function(contentType) {
var parser = this.__parser,
contentTypeOrig = "",
contentTypeNormalized = "";
// Use user-provided parser, if any
if (parser) {
return parser;
}
// See http://restpatterns.org/Glossary/MIME_Type
contentTypeOrig = contentType || "";
// Ignore parameters (e.g. the character set)
contentTypeNormalized = contentTypeOrig.replace(/;.*$/, "");
if ((/^application\/(\w|\.)*\+?json$/).test(contentTypeNormalized)) {
parser = qx.util.ResponseParser.PARSER.json;
}
if ((/^application\/xml$/).test(contentTypeNormalized)) {
parser = qx.util.ResponseParser.PARSER.xml;
}
// Deprecated
if ((/[^\/]+\/[^\+]+\+xml$/).test(contentTypeOrig)) {
parser = qx.util.ResponseParser.PARSER.xml;
}
return parser;
}
}
});