Skip to content

Instantly share code, notes, and snippets.

@bomzj
Last active August 20, 2022 10:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bomzj/4d5f64c62fa74361e768a276fe566cdf to your computer and use it in GitHub Desktop.
Save bomzj/4d5f64c62fa74361e768a276fe566cdf to your computer and use it in GitHub Desktop.
CORS Proxy AWS lambda function
/* Proxies http(s) requests to any endpoint even if doesn't allow CORS */
import axios from 'axios'
import qs from 'qs'
import https from 'https'
import http from 'http'
import fetch from 'node-fetch'
// Serialize query params that represents object with props
axios.defaults.paramsSerializer = params => qs.stringify(params)
export async function handler (event, context) {
// Handle CORS preflight request
if (event.httpMethod == 'OPTIONS') return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*"
}
}
// Extract target URL from request URL
let targetUrlStartIndex = event.path.indexOf('http://', 1)
if (targetUrlStartIndex == -1) {
targetUrlStartIndex = event.path.indexOf('https://', 1)
}
if (targetUrlStartIndex == -1) {
const noTargetError = "Target URL not found. Ensure CORS proxy request URL has the following format: " +
"protocol://host/path-to-cors-proxy-function/target-url"
console.log(noTargetError)
return {
statusCode: 400,
headers: {
"Access-Control-Allow-Origin": "*"
},
body: noTargetError
}
}
const targetUrl = event.path.substring(targetUrlStartIndex)
try {
console.log('\n')
console.log('Sending proxied request to', targetUrl, '\n')
console.log('Request Params:', event.queryStringParameters, '\n')
console.log('Request Headers:', event.headers, '\n')
// Remove Host header that can cause failure in HTTPS handshake,
// TODO: check whether some Headers affect that behaviour
delete event.headers.host
var response = await axios(targetUrl, {
method: event.httpMethod,
headers: event.headers,
// Preserve correct order of query string parameters(some services might require that)
params: Object.fromEntries(new URLSearchParams(event.rawQuery)),
data: event.body,
// prevents binary data to be corrupted, doesn't affect json or text data
responseType: 'arraybuffer',
})
} catch (error) {
console.log(error.toString())
return {
statusCode: error.response?.status || 500,
body: error.toString()
}
}
let data = response.data?.toString('Base64')
console.info('Sending the response back to the client\n')
console.log('Response Headers', response.headers, '\n')
return {
statusCode: response.status,
headers: {
...response.headers,
"Access-Control-Allow-Origin": "*"
},
body: data,
isBase64Encoded: true
}
}
@bomzj
Copy link
Author

bomzj commented Aug 20, 2022

It might be needed to rename the file extension from .js to .mjs when deploying to AWS or alike.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment