How I fixed Ajax Request to external resource errors (CSP) inside Discourse

AI-generated summary

Sören_Geier explains how to resolve AJAX request errors caused by the strict-origin-when-cross-origin CSP directive in Discourse. Key fixes include configuring the server to send the Access-Control-Allow-Origin header — either via the cors library or manually — and ensuring Access-Control-Allow-Headers includes necessary headers like Content-Type, Authorization, and Discourse-specific ones: discourse-present, discourse-logged-in, and discourse-track-view. A Node.js example demonstrates setting these headers directly in the server response, along with allowing HTTP methods via Access-Control-Allow-Methods. The goal is to permit cross-origin requests from Discourse while complying with CSP policies. Sören_Geier invites follow-up questions if further help is needed.

If you are having trouble with an AJAX request and think the error might be due to the strict-origin-when-cross-origin Content Security Policy (CSP) directive, there are a few things you can try to fix the issue (observe those in the error console of Chrome Devtools):

  1. Make sure the server is configured to include the Access-Control-Allow-Origin header in the response to the preflight request as well as the actual AJAX request. This header allows the resource to be accessed from the specified origin.

Here is an example of how you can configure the Access-Control-Allow-Origin header in a Node.js server using the cors library:

const cors = require('cors');

app.use(cors({
  origin: 'http://example.com',
  optionsSuccessStatus: 200
}));

Alternatively, you can include the Access-Control-Allow-Origin header directly in your server-side code. For example, in a Node.js server, you can set the header like this:

res.setHeader('Access-Control-Allow-Origin', '*');
  1. Make sure the server is configured to allow the headers that are being used in the preflight request and the actual AJAX request. This can be done by including these headers in the Access-Control-Allow-Headers header.

Here is an example of how you can configure the Access-Control-Allow-Headers header in a Node.js server:

const http = require('http');

const server = http.createServer((req, res) => {
    
    res.setHeader('Access-Control-Allow-Origin', '*'); // Add this line to allow the resource to be accessed from any origin
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS'); // Add this line to allow the specified HTTP methods to be used
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, discourse-present, discourse-logged-in, discourse-track-view'); // Add this line to allow the specified headers to be used

    if (req.url === '/getTopicLikes') {
        console.log('Request received');
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ likes: 100 }));
    } else {
        res.writeHead(404);
        res.end();
    }
});

server.listen(3000, () => {
    console.log('Server started on port 3000');
});

process.on('SIGINT', () => {
    console.log('Shutting down the server');
    server.close();
});

Please note the two additional allow headers that are Discourse specific:
discourse-present, discourse-logged-in, discourse-track-view

I hope these steps help fix the issue with your AJAX request. Let me know if you have any questions.

4 Likes