Skip to main content
Inspiring
February 11, 2022
Answered

How do you return Server Side Event "text/event-stream" text from a CFC function?

  • February 11, 2022
  • 1 reply
  • 510 views

Hi All,

 

TL;DR: Basically not sure how to stream text to the browser from a CFC.

 

I'm sure this is either simple or not possible but how do you return a Server Side Event text stream, using cfcontent type="text/event-stream" from a CFC function as opposed to a .cfm page?

 

I currently have a this code sample set up in a getmessages.cfm page and it works as expected:

 

<cfscript>
    cfheader( name="cache-control", value="no-cache, no-store, must-revalidate" );
    cfheader( name="pragma", value="no-cache" );
    cfheader( name="expires", value=getHttpTimeString(now()) );
    cfcontent( type="text/event-stream" );
    cfsetting( requesttimeout=60 );
    for ( i=1 ; i<=10 ; i++ ) {
        // end each data line with two #Chr(10)#
        if ( i == 1 ) {
            writeOutput("id: #createUUID()##Chr(10)#");
            writeOutput("data: {""msg"": ""Starting Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
        }
            writeOutput("retry: 10000#Chr(10)#");
            writeOutput("id: #createUUID()##Chr(10)#");
            writeOutput("data: {""msg"": ""#i# #timeFormat(now(), 'medium')#"", ""id"": #i#}#Chr(10)##Chr(10)#");
        if ( i == 10 ) {
            writeOutput("id: #createUUID()##Chr(10)#");
            writeOutput("data: {""msg"": ""Ending Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
        }
        cfflush();
    
        sleep(2000); 
    
    }
    // send zipCreated custom event
    writeOutput("id: #createUUID()##Chr(10)#");
    writeOutput("event: zipCreated#Chr(10)#");
    writeOutput("data: {""msg"": ""Zip Created."", ""id"": #i#} #Chr(10)##Chr(10)#");
</cfscript>

 

I am wondering how to do the same thing except from a CFC function instead.  So currently to consume this in a javascript file I use:

 

var source = new EventSource("getMessages.cfm", {
withCredentials: true,
});

 

 And instead I would like to be calling assuming the code was in the getMessages method: 

var source = new EventSource("MyCFC.cfc?method=getMessages&returnFormat=plain", {
withCredentials: true,
});

Is this possible? 

    This topic has been closed for replies.
    Correct answer BKBK

    Create the method getMessage with output attribute set to true.

    Something like:

    /* MyCFC.cfc */
    
    component {
    	void function getMessage() output=true {
    	    cfheader( name="cache-control", value="no-cache, no-store, must-revalidate" );
    	    cfheader( name="pragma", value="no-cache" );
    	    cfheader( name="expires", value=getHttpTimeString(now()) );
    	    cfcontent( type="text/event-stream" );
    	    cfsetting( requesttimeout=60 );
    	    for ( i=1 ; i<=10 ; i++ ) {
    	        // end each data line with two #Chr(10)#
    	        if ( i == 1 ) {
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""Starting Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	        }
    	            writeOutput("retry: 10000#Chr(10)#");
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""#i# #timeFormat(now(), 'medium')#"", ""id"": #i#}#Chr(10)##Chr(10)#");
    	        if ( i == 10 ) {
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""Ending Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	        }
    	        cfflush();
    	    
    	        sleep(2000); 
    	    
    	    }
    	    // send zipCreated custom event
    	    writeOutput("id: #createUUID()##Chr(10)#");
    	    writeOutput("event: zipCreated#Chr(10)#");
    	    writeOutput("data: {""msg"": ""Zip Created."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	
    	}
    }

     

    /* testPage.cfm (in same directory as MyCFC.cfc) */
    
    <cfscript>
    testObj=createobject("component", "MyCFC");
    testObj.getMessage();	
    </cfscript>
    

    1 reply

    BKBK
    Community Expert
    BKBKCommunity ExpertCorrect answer
    Community Expert
    February 11, 2022

    Create the method getMessage with output attribute set to true.

    Something like:

    /* MyCFC.cfc */
    
    component {
    	void function getMessage() output=true {
    	    cfheader( name="cache-control", value="no-cache, no-store, must-revalidate" );
    	    cfheader( name="pragma", value="no-cache" );
    	    cfheader( name="expires", value=getHttpTimeString(now()) );
    	    cfcontent( type="text/event-stream" );
    	    cfsetting( requesttimeout=60 );
    	    for ( i=1 ; i<=10 ; i++ ) {
    	        // end each data line with two #Chr(10)#
    	        if ( i == 1 ) {
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""Starting Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	        }
    	            writeOutput("retry: 10000#Chr(10)#");
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""#i# #timeFormat(now(), 'medium')#"", ""id"": #i#}#Chr(10)##Chr(10)#");
    	        if ( i == 10 ) {
    	            writeOutput("id: #createUUID()##Chr(10)#");
    	            writeOutput("data: {""msg"": ""Ending Process..."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	        }
    	        cfflush();
    	    
    	        sleep(2000); 
    	    
    	    }
    	    // send zipCreated custom event
    	    writeOutput("id: #createUUID()##Chr(10)#");
    	    writeOutput("event: zipCreated#Chr(10)#");
    	    writeOutput("data: {""msg"": ""Zip Created."", ""id"": #i#} #Chr(10)##Chr(10)#");
    	
    	}
    }

     

    /* testPage.cfm (in same directory as MyCFC.cfc) */
    
    <cfscript>
    testObj=createobject("component", "MyCFC");
    testObj.getMessage();	
    </cfscript>
    
    TwoEdgeAuthor
    Inspiring
    February 11, 2022

    Thanks! That seems to do the trick.