Unable to connect to event stream

Hello! I am trying to integrate server events into an existing application, but I am having issues connecting to the event stream.

I was successfully able to create and subscribe to the event stream of a fresh test project, simply by adding the ServerEventsFeature plugin, and accessing it from a Vue front end project. I added the plugin the same way to the existing application, and tried to connect from both the application’s front end and the test Vue project, but I receive this CORS error:

Access to resource at 'http://localhost:8585/event-stream?channel=test&t=1585230470861' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

When I try to access the URL directly, I receive a 404 error. Here is my apphost.cs file:

public class AppHost : AppHostHttpListenerPoolBase
        {
            public ILog log = LogManager.GetLogger(typeof(AppHost));
            public AppHost()
                : base("Cognos Loading Utility", typeof(CustomerService).Assembly) { }

            public override void Configure(Container container)
            {
                LogManager.LogFactory = new NLogFactory();              
                log.InfoFormat("Loading Configuration");

                var appSettings = new AppSettings();
                var fc = appSettings.Get<FolderConfiguration>("FolderConfiguration");
                container.Register<IFolderConfiguration>(fc);
                log.InfoFormat("Loading Configuration Folder: Input Folder: ({0}) Output Folder: ({1})", fc.InputFolder, fc.OutputFolder);

                Plugins.Add(new OpenApiFeature());
                log.InfoFormat("Loading OpenAPI aka Swagger");

                var connString = ConfigUtils.GetConnectionString("Cognos");
                OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(connString, new SqlServer2016OrmLiteDialectProvider());
                container.Register<IDbConnectionFactory>(dbFactory);

                log.InfoFormat("Connection string:{0}", connString);
                log.InfoFormat("Configuration Loaded");
                log.InfoFormat("Migrate Database");
                var dbMigration = new DatabaseMigration(dbFactory);
                dbMigration.MigrateDatabase();

                Plugins.Add(new ServerEventsFeature());

                Plugins.Add(new CorsFeature(
                         allowOriginWhitelist: ConfigurationManager.AppSettings["CorsOriginWhitelist"].Split(','),
                         allowedMethods: "GET,POST,PUT,OPTIONS",
                         allowCredentials: true,
                         allowedHeaders: "Authorization, Content-Type"
                        ));
            }

And here is the front-end code I’m using:

this.sseStream = new EventSource('http://localhost:8585/event-stream?channel=test&t=' + new Date().getTime())

    this.sseStream.addEventListener('connect', event => {
      console.log('Connect event fired.')
      console.log(event.data)
    }, false)

    this.sseStream.addEventListener('open', event => {
      console.log('Open event fired.')
      console.log(event.data)
    }, false)

    this.sseStream.addEventListener('message', event => {
      console.log('Message event fired.')
      console.log(event.data)
    }, false)

Any help would be very appreciated, thanks!

It suggests your CorsFeature allowOriginWhitelist doesn’t match the origin.

Note you should use the JS/TypeScript Server Events Client to access ServiceStack’s SSE endpoint.

Thank you for your response. I should have mentioned, the allowOriginWhitelist does indeed match the origin, this is the whitelist I’m using:

<add key="CorsOriginWhitelist" value="http://localhost:8000,http://localhost:8080" xdt:Transform="Replace" xdt:Locator="Match(key)" />

These addresses correspond to the two front end projects. I don’t get CORS issues when calling the application’s service interface methods from the application’s front end, which use the JsonServiceClient.

I will look at integrating the server events client, I just wanted to quickly test the implementation from the ServiceStack side before focusing on the front end. Meanwhile, any other ideas would be much appreciated!

Can you post the raw HTTP Headers of the failed requests.

Looks like it is just a 404 somehow.

Request:

GET /event-stream?channel=test&t=1585241579633 HTTP/1.1
Host: localhost:8585
Connection: keep-alive
Accept: text/event-stream
Cache-Control: no-cache
Sec-Fetch-Dest: empty
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
Origin: http://localhost:8000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Referer: http://localhost:8000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fr;q=0.8

Response:

HTTP/1.1 404 Not Found
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Thu, 26 Mar 2020 16:52:59 GMT
Connection: close
Content-Length: 315

That Request is not being served by ServiceStack, it suggests something is intercepting it or ServiceStack isn’t configured to serve at that URL.

Fair enough, it’s strange. Nothing should be intercepting since I can make other calls successfully from the same front end to that endpoint, and changing the default URL for the ServerEventsFeature yields the same result.

I’ll keep investigating. Last question for now, would it make a difference that the app is being run as a Windows service rather than on IIS? Only thing I can think of. Thanks for your help, mythz!

It changes the host that’s running ServiceStack, e.g. on .NET Framework WindowsService uses a HttpListener SelfHost instead of IIS/ASP.NET. But ServiceStack is either not configured or something else is listening on that port. Does /metadata return ServiceStack’s metadata page?

Strangely no, it also returns 404. And yet, the application responds to calls using the JsonServiceClient to http://localhost:8585/api. What configuration could cause this? I’m not entirely sure how this application is set up, since I’ve used IIS for the ServiceStack applications I’ve set up myself.

Then you have ServiceStack hosted at /api?

In which case your SSE endpoint is at /api/event-stream and your metadata page at /api/metadata.

Oof, I had a sinking feeling I was being a noob. Can’t believe I missed that. Thanks for your help and patience, mythz!

1 Like