Created
August 22, 2023 18:52
-
-
Save JoeyBurzynski/44cbe15343d64ff611c2998fc0d51dd9 to your computer and use it in GitHub Desktop.
Vercel Function to Echo HTTP Headers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// "cf-connecting-ip" should contain true client IP when Cloudflare managed | |
// transform rule ("Add visitor location headers") is enabled. | |
// See: https://share.marketkarma.com/cloudflare-managed-transform-add-geoip-http-headers.png | |
const HTTP_OK = 200; | |
const HTTP_INTERNAL_SERVER_ERROR = 500; | |
/** | |
* Filters out headers that are not allowed, sorts headers alphabetically, | |
* and converts headers to JSON. | |
* @param {Object} headers - The headers object. | |
* @returns {Object} - The filtered and sorted headers object. | |
*/ | |
const filterAndSortHeaders = (headers) => { | |
return Object.keys(headers) | |
.sort((a, b) => a.localeCompare(b)) | |
.filter(header => allowedHeadersSet.has(header)) | |
.reduce((obj, header) => { | |
obj[header] = headers[header]; | |
return obj; | |
}, {}); | |
}; | |
/** | |
* Sets CORS headers for the response. | |
* @param {Object} res - The response object. | |
*/ | |
const setCORSHeaders = (res) => { | |
res.setHeader('Access-Control-Allow-Origin', '*'); | |
res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS'); | |
res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); | |
}; | |
/** | |
* Returns the HTTP headers of the request. | |
* @param {Object} req - The request object. | |
* @param {Object} res - The response object. | |
* @returns {Promise<void>} - A promise that resolves with the response. | |
*/ | |
module.exports = async (req, res) => { | |
try { | |
const prettyPrintedJSON = JSON.stringify({ | |
headers: filterAndSortHeaders(req.headers) | |
}, null, 2); | |
setCORSHeaders(res); | |
res.setHeader('Content-Type', 'application/json'); | |
res.status(HTTP_OK).send(prettyPrintedJSON); | |
} catch (error) { | |
console.error(`Error processing request: ${error.message}`); | |
const errorMessage = process.env.NODE_ENV === 'development' ? `Internal server error: ${error.message}` : 'Internal server error'; | |
res.status(HTTP_INTERNAL_SERVER_ERROR).send(errorMessage); | |
} | |
}; | |
/** | |
* An array of allowed headers. | |
* @type {string[]} | |
*/ | |
const allowedHeadersSet = new Set([ | |
"accept", | |
"accept-encoding", | |
"accept-language", | |
"cache-control", | |
"cdn-loop", | |
"cf-connecting-ip", | |
"cf-ipcity", | |
"cf-ipcontinent", | |
"cf-ipcountry", | |
"cf-iplatitude", | |
"cf-iplongitude", | |
"cf-metro-code", | |
"cf-postal-code", | |
"cf-ray", | |
"cf-region", | |
"cf-region-code", | |
"cf-timezone", | |
"cf-visitor", | |
"connection", | |
"forwarded", | |
"host", | |
"priority", | |
"sec-ch-ua", | |
"sec-ch-ua-mobile", | |
"sec-ch-ua-platform", | |
"sec-fetch-dest", | |
"sec-fetch-mode", | |
"sec-fetch-site", | |
"sec-fetch-user", | |
"upgrade-insecure-requests", | |
"user-agent", | |
"x-forwarded-for", | |
"x-forwarded-host", | |
"x-forwarded-proto", | |
"x-real-ip", | |
"x-vercel-deployment-url", | |
"x-vercel-forwarded-for", | |
"x-vercel-id", | |
"x-vercel-ip-city", | |
"x-vercel-ip-country", | |
"x-vercel-ip-country-region", | |
"x-vercel-ip-latitude", | |
"x-vercel-ip-longitude", | |
"x-vercel-ip-timezone", | |
"x-vercel-proxied-for", | |
"x-vercel-proxy-signature", | |
"x-vercel-proxy-signature-ts" | |
]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment