Skip to content

Instantly share code, notes, and snippets.

@shiguruikai
Last active May 3, 2025 13:59
Show Gist options
  • Save shiguruikai/d40c4dcfadb6b9078d1b3744589711d5 to your computer and use it in GitHub Desktop.
Save shiguruikai/d40c4dcfadb6b9078d1b3744589711d5 to your computer and use it in GitHub Desktop.
CORS Proxy server for Google Cloud Run functions
const functions = require('@google-cloud/functions-framework');
const compression = require('compression');
const express = require('express');
const app = express();
app.use(compression());
app.disable('x-powered-by');
app.all('/', async (req, res) => {
try {
if (!req.query.url) {
return res.status(400).send('Missing "url" query parameter.');
}
let targetUrl;
try {
targetUrl = new URL(req.query.url);
} catch {
return res.status(400).send('Invalid "url" query parameter.');
}
res.set('Access-Control-Allow-Origin', req.headers['origin'] || '*');
if (req.method === 'OPTIONS') {
res.set('Access-Control-Allow-Methods', 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS');
res.set('Access-Control-Allow-Headers', req.headers['access-control-request-headers'] || '*');
res.set('Access-Control-Allow-Credentials', 'true');
res.set('Access-Control-Max-Age', '3600');
return res.sendStatus(204);
}
const targetHeaders = { ...req.headers };
delete targetHeaders['connection'];
delete targetHeaders['content-length'];
delete targetHeaders['origin'];
delete targetHeaders['proxy-connection'];
delete targetHeaders['referer'];
delete targetHeaders['transfer-encoding'];
targetHeaders['host'] = targetUrl.host;
const fetchOptions = {
method: req.method,
headers: targetHeaders,
};
if (req.method !== 'GET' && req.method !== 'HEAD') {
fetchOptions.body = req.rawBody;
}
const targetResponse = await fetch(targetUrl, fetchOptions);
for (const [header, value] of targetResponse.headers.entries()) {
const lowerHeaderName = header.toLowerCase();
if (
!lowerHeaderName.startsWith('access-control-') &&
lowerHeaderName !== 'connection' &&
lowerHeaderName !== 'content-encoding' &&
lowerHeaderName !== 'content-length' &&
lowerHeaderName !== 'proxy-connection' &&
lowerHeaderName !== 'transfer-encoding'
) {
res.set(header, value);
}
}
const rawBody = Buffer.from(await targetResponse.arrayBuffer());
res.status(targetResponse.status).send(rawBody);
} catch (error) {
res.status(500).send(`Proxy error: ${error.message}`);
}
});
functions.http('corsProxy', app);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment