6

We have been using cometd with pushTopic. But we facing an issue an issue in summer 18 org that handshake with cometd is failing in lightning component. if we use lightning component directly in lightning page cometd is working. But if we use a visual force(ltng:outApp) page to display component cometd is not working. In spring 18 it used to work in both classic and lightning.

Here is sample code for that is working in spring 18 but not in summer 18.

TestPage.vf

<apex:page sidebar="false">
    <apex:includeLightning />
    <div id="lightning" />

    <script>
        $Lightning.use("c:TestApp", function() {
            $Lightning.createComponent("c:TestComp",{},"lightning",function(cmp) {});
        });
    </script>

</apex:page>

TestController.cls

public class TestController {
    @auraEnabled public static String fetchSessionId() {
        return UserInfo.getSessionId();
    }
}

TestApp.app

<aura:application extends ="ltng:outApp">
    <aura:dependency resource="markup://c:TestComp"/>
</aura:application>

TestComp.cmp

<aura:component controller="TestController" implements="force:hasRecordId,force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,forceCommunity:availableForAllPageTypes,force:lightningQuickAction">
    <aura:attribute name="isPushTopicWorking" type="Boolean" default="false"/>
    <ltng:require scripts="{!join(',',
                           $Resource.<staticResouceName> + '/cometd.js',
                           $Resource.<staticResouceName> + '/jquery_1_5_1.js',
                           $Resource.<staticResouceName> + '/json2.js',
                           $Resource.<staticResouceName> + '/jquery_cometd.js')}"
                  afterScriptsLoaded="{!c.afterScriptsLoaded}" />

    isPushTopicWorking = {!v.isPushTopicWorking}
</aura:component>

Testcontroller.js

({
    afterScriptsLoaded : function(component, event, helper) {
        var action = component.get('c.fetchSessionId');
        action.setCallback(this, function (response)  {                    
            var sessionId = response.getReturnValue();
            helper.setupCometd(component, helper, sessionId);
        });
        $A.enqueueAction(action);
    },
})

Helper.js

({
    setupCometd : function(component, helper, sessionId) {

        console.log($.cometd);

        $.cometd.init({
            url: window.location.protocol+'//'+window.location.hostname+'/cometd/24.0/',            
            requestHeaders: { Authorization:'OAuth '+sessionId}
        });


        $.cometd.addListener('/meta/handshake', function(message) {
            console.log(message.successful);
        });
        $.cometd.subscribe('/topic/pustopicname',  $A.getCallback(function(message) {
            component.set('v.isPushTopicWorking',true);
        }));


    }
})

In summer 18 org we can see error is console log enter image description here

There is no documentation in release notes for change in cometd. What can be causing this issue.

  • Just for a lark, try disabling the "Remove Instance Names from URLs for Visualforce, Community Builder, Site.com Studio, and Content Files" Critical Update. Give it a few hours to percolate through the system and then try again. Do you still get the same issue? – Charles T May 12 '18 at 14:31
4

I don't know if this is the right answer but I'm gonna drop the possibility here...

Locker Service defines a few trusted origin domains. Take a look at this commit: https://github.com/forcedotcom/aura/commit/495eaccdc3292a6cf2dcd2c2347c0329c06339e0#diff-7029ab74270f2b05e936f8a47738b1a7

In the code base as of Spring 18's release date, we see (https://github.com/forcedotcom/aura/blob/259fe052729103f069e453978a18ae24f747f6dc/aura-resources/src/main/resources/aura/resources/lockerservice/aura-locker.js):

// for relative urls enable sending credentials
if (scriptUrl.indexOf('/') === 0) {
  xhr.withCredentials = true;
}

In other words, it used to be that any XHR made to a relative URL would be made with credentials. In a more recent commit (prior to the current one), we see:

const TRUSTED_CORS_DOMAINS = /(\.lightning\.(.*\.)?force|\.salesforce)\.com$/;
/* many lines skipped */
if (normalized.hostname.match(TRUSTED_DOMAINS)) {
    xhr.withCredentials = true;
}

In the current code base we see:

const TRUSTED_DOMAINS = /\.(force|salesforce)\.com$/;
/* many lines skipped */
if (normalized.hostname.match(TRUSTED_DOMAINS)) {
    xhr.withCredentials = true;
}

But... if you're running Lightning inside Visualforce via Lightning Out, your Lightning is in fact being served from the Visualforce domain. And if you have enabled the update "Remove Instance Names from URLs for Visualforce, Community Builder, Site.com Studio, and Content Files" then your VF domain name changes from mydomain--c.naXX.visual.force.com to mydomain--c.visualforce.com which does NOT match the regexes above. So I wonder if the Lightning Locker team neglected to consider this possibility?

| improve this answer | |
  • It seems like you are right.. Salesforce support disabled the critical update "Remove Instance Names from URLs for Visualforce, Community Builder, Site.com Studio, and Content Files" on org it is working fine. We will ask salesforce to resolve this issue by citing your findings. – Manjot Singh May 14 '18 at 6:43
  • Yes, please pass them the link to this thread. There are clearly a few gaps in the system that haven't adapted to the new URL format. – Charles T May 14 '18 at 11:50
  • 1
    @CharlesT Thanks for your investigation. Its great to see the community tracking issues down to the exact commit. Bug W-4992943 has been filed for Locker Service team resolve this issue. – Ravi Jayaramappa May 14 '18 at 19:16
  • Great to hear. Once I'd noticed the error message referenced .visualforce.com I figured maybe the lockerized XMLHttpRequest was responsible for the issue. So I looked for that in the Locker JS and compared to prior commits. – Charles T May 14 '18 at 20:04
  • @CharlesT, thanks for debugging this issue. A fix is on the way. – JF Paradis May 15 '18 at 0:37
0

There are several changes that could be causing this behavior. First, I'll assume you're aware that Lightning pages are served from a different server than Visualforce pages and have a different session Id as a consequence. For that reason, it's always preferable to keep everything in Lightning if possible. The 401 unauthorized error would seem to be consistent with one of the security enhancements. See Lightning Container Components Have New Security Enhancements

It isn't clear from reading your code, but its possible the issue could also be related to this change: Lightning Quick Action and Salesforce Classic Publisher JavaScript APIs and it would seem to be worth looking at.

In any case, I think you'll want to use the Lightning approach if you don't use the component on VisualForce pages. That would seem to be a "best practice".

| improve this answer | |
  • The code that was posted is neither a Lightning Container Component nor related to Quick Actions or Publisher APIs. Presumably the OP is describing a component written first for Lightning but also capable of being surfaced in Visualforce (via Lightning Out) so that the same functionality can be delivered to users still on Classic. What do you mean when you say "use the Lightning approach" as a best practice? Salesforce has expressed full support for using CometD in Lightning Components. – Charles T May 12 '18 at 14:03
  • @CharlesT "Lightning Approach" was a reference to avoiding going cross domain between the Visualforce server and the Lightning Server since the Lightning component is being served from the Lightning server. – crmprogdev May 12 '18 at 14:17
  • Hmm that gives me an idea... – Charles T May 12 '18 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.