I have written a little servlet that outputs data in the form of an RSS feed. It's running on my webserver at /services/rss.servlet and is returning data nicely.
In my webpage I am attempting to load data from the rss servlet like so:
$(document).ready(function() {
$.get("/services/rss.servlet")
.done(function(data) {
console.log("Success: " + data);
})
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ", " + error;
console.log( "Request Failed: " + err );
});
});
MOST of the time, this works fine and I get data. But every now and then, the request fails and I see the following request in my network debugging page:
Request GET /ajax/services/rss.servlet HTTP/1.1
Why am I seeing /ajax prepended to my URL? It seems completely undocumented in JQuery. In particular, I notice this behavior all the time in IE9 with quirks mode, but not in IE9 with standard browser mode.
I discovered that this problem was unique to a "feature" of Adobe CQ/WEM.
In a "normal" layout, CQ would have the following subdirectories publicly exposed:
www.example.com/apps
www.example.com/libs
www.example.com/etc
However, CQ contains code allowing it to be hosted in a relative URL deeper than the document root, in case your directory structure happened to be...
www.example.com/subdirectory/cqRoot/apps
www.example.com/subdirectory/cqRoot/etc
www.example.com/subdirectory/cqRoot/libs
The code that supports this is all client-side javascript which scans the <head>
for these directories and figures out where CQ "ought to be".
In our case, one of the first items in our <head>
was <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
, and CQ thought this meant the application was stored under /ajax.
There is a configuration to defeat this feature starting in CQ 5.6 from the Felix console. http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manager.topic.685.html/forum__omci-we_are_on_cq54.html
You can also force it to be disabled in your <head>
, so that it does not auto-detect.
<script>
window.CQURLInfo = window.CQURLInfo || {};
CQURLInfo.contextPath = "";
</script>