When the commerce system has to deliver the end user's web pages, CoreMedia Digital Experience Platform 8 offers a way to enrich those web pages with content from the CoreMedia CMS; the fragment connector. Figure 5.3, “The Perfect Chef header as a fragment for the Aurora shop” shows the IBM Aurora demo shop page with the integrated CoreMedia PerfectChef header.
Integrating content from the CoreMedia system into the IBM WebSphere Commerce pages presents a challenge due to the same-origin policy:
The image above shows a typical situation when a user requests an IBM commerce page that includes CoreMedia fragments.
The page request from the end user is sent to the IBM WebSphere Commerce server.
While rendering the page, the commerce server requests a fragment from the CAE.
The returned fragment contains itself parts that must be delivered dynamically. Take the login button. It is user specific, hence it must not be cached. The CoreMedia LiveContext Blueprint may include such parts via Ajax requests or as ESI tags, depending on the capabilities of the component which sent the request.
The commerce server returns the complete page, including the fragment that was rendered by the CAE.
Because it is assumed that the CoreMedia LiveContext fragment contains a dynamic part, which must not be cached, the browser tries to trigger an Ajax request to the CAE. But this breaks the same-origin policy and will not succeed.
Solution 1: Access-Control-Allow-Origin
The first solution is built into the CoreMedia Blueprint workspace, so you may use it out of the box. The idea
is to customize the same origin policy by setting the Access-Control-Allow-Origin
HTTP header
accordingly.
CoreMedia Blueprint contains a servlet filter that does this job: The CrossDomainEnabler
.
The picture shows the relevant parts of the request flow:
For every Ajax request that is called from within a fragment, that was delivered by the commerce system, the JavaScript will trigger an
HTTP OPTIONS
request, asking for the allowance to set theX-Requested-With
header.The
CrossDomainEnabler
receives that request and allows that header to be sent for the given Ajax request.The JavaScript client triggers the Ajax request and sets the
X-Requested-With
header toXMLHttpRequest
.The
CrossDomainEnabler
intercepts this request and writes its cross domain whitelist to theAccess-Control-Allow-Origin
header of the response before it forwards the request to the corresponding handler.The browser receives the response and accepts that it.
The CrossDomainEnabler
does not allow every cross domain access. Instead, it must be configured
within the Spring application context with domains that are meant to be safe. To customize the
CrossDomainEnabler
, define the property livecontext.crossdomain.whitelist
in the application context with a comma separated list of domains, as in the example below.
livecontext.crossdomain.whitelist=http://my.shop.domain1,http://my.shop.domain2
There are two additional properties that you may want to change.
The
ajaxIndicatorHeaderName
is the name of a header that the cross domain enabler uses to identify Ajax requests. Its default value isX-Requested-With
which is used by jQuery to mark Ajax requests.The
ajaxIndicatorHeaderValue
is the value that the header must contain in order to be identified as an Ajax request. Again the default value is set to jQuery'sXMLHttpRequest
.
Caution | |
---|---|
Per default springs |
Solution 2: The Proxy
To solve this problem the classical way, the Ajax request needs to be sent to the same origin than the whole page request in step 1 was. The next image shows the solution to this problem: A reverse proxy needs to be put in front of both the CAE and the WCS.
Actually, you may use any proxy you fell comfortable with. The following snippet shows the configuration
for a Varnish. Two back ends were defined, one for the CoreMedia LiveContext CAE named blueprint
and another one for the IBM WebSphere Commerce server named commerce
.
The vcl_recv
subroutine is called for every request that reaches the Varnish instance. Inside of it
the request object req
is examined that represents the current request. If its url
property starts with /blueprint/
, it will be sent to the CoreMedia LiveContext CAE. Any other
request will be sent to the commerce system. (~
means "contains" and the argument is a regular expression)
Now, if you request an Aurora URL through Varnish and the resulting page contains a CoreMedia LiveContext fragment including a dynamic part that must not be cached, like the sign in button, the Ajax request will work as expected.
backend commerce { .host = "ham-its0484-v"; .port = "80"; } backend blueprint { .host = "ham-its0484"; .port = "40081"; } sub vcl_recv { if (req.url ~ "^/blueprint/") { set req.backend = blueprint; } else { set req.backend = commerce; } }