Meteor added a way to suppress CORS headers in 2.14 (DISABLE_SOCKJS_CORS), which is great. The default ones were problematic.
However, removing them altogether breaks Cordova applications.
Is there a way to slip in a “Access-Control-Allow-Origin” header in the response to that intial to “sockjs/info” call? It would be fantastic if I could manually add that header with the value I need.
If I know things right then you should always be able to manipulate all incoming requests using WebApp.rawConnectHandlers.use and then add a middleware that adds respective headers or call next to pass handling on to all other requests.
Thanks for the response. Between the connect and rawConnect handlers, I can get some things, but the sockjs stuff seems to be completely inaccessible.
I have a feeling I will need to access internal ‘use-at-your-own-risk’ properties at this point, but I don’t know what those would be. Nothing I have tried has worked.
I no longer deal with this logic in the Meteor app, instead add this header on the edge using Cloudflare Workers. Far easier to deal with, modify, etc. without re-deploying the Meteor app each time.
This is looks a bit cludgy, but I found an answer looking at the Meteor source code. I am not sure why they implemented the listener replacement this way, but I figured they had a reason.
Here are the tricky parts from the class. Once in your custom ‘preprocess’ function, you can check the url (like for /sockjs/), and do what you want.
/**
This class is used to intercept all requests and modify the response headers.
This was created to add CORS headers to the responses.
The mechanism used here was taken from the meteor source code.
private initialize()
{
const EVENT = 'request';
const httpServer = WebApp.httpServer;
const oldHttpServerListeners: Function[] = httpServer.listeners(EVENT).slice(0);
httpServer.removeAllListeners(EVENT);
// In the meteor source code, this process is done to both upgrade and request. I don't think we need to mess with the header
// on an upgrade. Note, in the meteor docs, it says that the "upgrade" event type has different arguments then request,
// which is probably why they use the 'arguments' object in the closure below.
const self = this;
const newListener = function (request: IncomingMessage, response: ServerResponse) {
// Store arguments for use within the closure below
const args = arguments;
self.preprocess(httpServer, request, response);
oldHttpServerListeners.forEach(function (oldListener) {
oldListener.apply(httpServer, args);
});
self.postprocess(httpServer, request, response);
};
httpServer.addListener(EVENT, newListener);
}