Ich stand heute vor dem eher unbedeutenden Problem, dass Prototype-JS (aktuell Version 1.6.0) bei einer Serverantwort nur dann JSON selbständig interpretiert, wenn entweder im Header “X-JSON” oder als Content-Type “application/json” geliefert wird. Weder das Eine noch das Andere wären aus technischer Sicht problematisch gewesen umzusetzen, jedoch wollte ich einen Content-Type “text/x-json” senden, da dieses nach Ratschlag der RFC-1521 in diesem Fall passender wäre, da es sich bei JSON um ein menschenlesbares Textformat handelt – “application” hingegen sollte nur für Binärinformationen verwendet werden. Es sei nur nebenbei erwähnt, dass die genannte RFC aus dem Jahr 1993 stammt, als an JSON noch nicht zu denken war und somit nur eine Richtlinie darstellt.
Die entscheidende Stelle in Prototype war auch recht schnell gefunden. Es handelt sich dabei um die Klasse Ajax.Response und die Methode _getResponseJSON(), worin der Content-Type geprüft wird. Die Frage war nur: Wie passe ich die Abfrage an, ohne den Originalcode von PrototypeJS zu ändern und gleichzeitig zu gewährleisten, dass alle von Prototype durchgeführten Ajax-Requests trotzdem die erweiterte Überprüfung auf Content-Type “text/x-json” verwenden?
Ihr fragt Euch vlt.: “hey Mann, warum so kompliziert? Änder einfach die If-Abfrage in Prototype und gut is!”. Klar, könnte man machen, aber wenn eine neue Prototype-Version herauskommt, die ich dann verwenden will, gingen meine Anpassungen verloren! “Never change sources you don’t own!” Könnte man dazu auch sagen. ![]()
“Na gut, dann schreib doch einfach eine neue Klasse, die von Ajax.Response erbt und arbeite dann mit dem Objekt dieser Klasse…”. Genau das war die Lösung – fast, denn wie sorge ich dafür, dass auch die Hilfsklassen wie Ajax.Updater meine Ajax.Response nutzen?
Hier kommt ein kleines Javascript-Detail zum Tragen, was in anderen Sprachen wie Java meines Wissens nach nicht so einfach möglich ist. Es existiert nämlich kein Packagekonzept, also warum schreibe ich nicht eine “Klasse”, mit dem globalen Namen Ajax.Response, die wiederum von Ajax.Response (aus PrototypeJS) erbt und nur die Methode _getResponseJSON() enthält und diese somit überschreibt? Klingt irgendwie nach Inzest!?….funktioniert aber. ![]()
Hier das Resultat:
Ajax.Response = Class.create(Ajax.Response, {
_getResponseJSON: function() {
var options = this.request.options;
if (!options.evalJSON
|| (options.evalJSON != 'force'
&& !(this.getHeader('Content-type') || '').include('application/json')
&& !(this.getHeader('Content-type') || '').include('text/x-json'))
|| this.responseText.blank()){
return null;
}
try {
return this.responseText.evalJSON(options.sanitizeJSON);
} catch (e) {
this.request.dispatchException(e);
}
}
});Sollte es bei einer kommenden Version somit zu Konflikten kommen, bräuchte man nur noch seine Anpassungen mit dieser neuen Version vergleichen. Die weitere Funktionsweise bleibt weiterhin erhalten.
Share this Post[?]
