Skip to content

Commit

Permalink
simplify backend and add cors retries on frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
maxhniebergall committed Dec 29, 2024
1 parent b314209 commit 292913b
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 44 deletions.
65 changes: 26 additions & 39 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,48 +55,45 @@ logger.info('Configured CORS origins: %O', allowedOrigins);
app.use((req, res, next) => {
const origin = req.headers.origin;

// Helper to check if origin is allowed
const isAllowedOrigin = !origin || allowedOrigins.includes(origin);
logger.debug('CORS middleware: Processing request from origin: %s', origin);
logger.debug('Allowed origins: %O', allowedOrigins);

if (!isDbReady) {
logger.warn('Database not ready, returning 503');
return res.status(503).json({
error: 'Service initializing, please try again in a moment'
});
}

// Set CORS headers for all responses, including errors
res.header('Access-Control-Allow-Origin', isAllowedOrigin ? (origin || '*') : 'null');
res.header('Access-Control-Allow-Credentials', 'true');
// If origin is in our allowed list, set it as allowed
if (origin && allowedOrigins.includes(origin)) {
logger.debug('Setting CORS for allowed origin: %s', origin);
res.header('Access-Control-Allow-Origin', origin);
} else {
// For development or when origin isn't present
logger.debug('Using wildcard CORS as origin not in allowed list');
res.header('Access-Control-Allow-Origin', '*');
}

// Set other CORS headers before any async operations
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Frontend-Hash');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Max-Age', '86400');

// Handle preflight
res.setHeader('X-Build-Hash', BUILD_HASH);

// Handle preflight immediately
if (req.method === 'OPTIONS') {
logger.debug('Handling OPTIONS preflight request');
return res.status(204).end();
}

// Handle disallowed origins
if (!isAllowedOrigin) {
logger.warn(`CORS blocked origin: ${origin}`);
return res.status(403).json({
error: 'The CORS policy for this site does not allow access from the specified Origin.'
});
}

// Ensure CORS headers are sent even when errors occur
const oldSend = res.send;
res.send = function (data) {
// Ensure CORS headers are set before sending response
res.header('Access-Control-Allow-Origin', origin || '*');
res.header('Access-Control-Allow-Credentials', 'true');
return oldSend.apply(res, arguments);
};


next();
});

// Add build hash to all responses
app.use((req, res, next) => {
res.setHeader('X-Build-Hash', BUILD_HASH);
next();
});


import { fileURLToPath } from 'url';
import { dirname } from 'path';

Expand All @@ -116,16 +113,6 @@ await db.connect().then(() => {
process.exit(1);
});

// Add middleware to check DB readiness
app.use((req, res, next) => {
if (!isDbReady) {
return res.status(503).json({
error: 'Service initializing, please try again in a moment'
});
}
next();
});

app.post("/api/createStatement", async (req, res) => {
if (req.body.uuid && req.body.value) {
try {
Expand Down
27 changes: 22 additions & 5 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,28 @@ function App() {
return config;
});

// Log build hashes from responses
axios.interceptors.response.use((response) => {
console.log(`Backend build: ${response.headers['x-build-hash']}`);
return response;
});
// Add retry logic for CORS errors
axios.interceptors.response.use(
(response) => {
console.log(`Backend build: ${response.headers['x-build-hash']}`);
return response;
},
async (error) => {
const config = error.config;

// If error is CORS-related and we haven't retried yet
if (!config._retry && error.message.includes('CORS')) {
config._retry = true;
console.warn('CORS error detected, retrying request once');

// Wait a short moment before retrying
await new Promise(resolve => setTimeout(resolve, 100));
return axios(config);
}

return Promise.reject(error);
}
);
}, []);

return (
Expand Down

0 comments on commit 292913b

Please sign in to comment.