Skip to content

Instantly share code, notes, and snippets.

@bangingheads
Last active April 14, 2022 13:47
Show Gist options
  • Save bangingheads/c49756ff71b8fc337f2abf16c46a03f7 to your computer and use it in GitHub Desktop.
Save bangingheads/c49756ff71b8fc337f2abf16c46a03f7 to your computer and use it in GitHub Desktop.
Using Cloudflare Workers to Make Requests to Riot Games API
/*
Cloudflare Workers Script to make request to the Riot Games API
By: BangingHeads
Supports GET Requests
Supports Path and GET Parameters as GET Parameters
Example path: https://example.bangingheads.workers.dev/api/?region=na1&endpoint=/lol/summoner/v4/summoners/by-name/{summonerName}&summonerName=Headbang
Use Guide on Hextech Docs (https://hextechdocs.dev) if you need more help
*/
// Your Riot Games API Key
const API_KEY = 'RGAPI-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX';
// The path to use, default /api/
// If you do more to this script you potentially could want multiple paths
const API_ENDPOINT = '/api/';
// Time in seconds to cache responses
// You may want lower or higher depending on how real time you need info
const CACHE_TIME = 600;
// Array of origins allowed, use ["*"] for all origins
// or full domain https://www.google.com
const ALLOWED_ORIGINS = ["https://www.google.com"]
// Don't modify below unless you know what you are doing
// Creates URL Query string from Object p1=1&p2=2
const createQueryParams = params =>
Object.keys(params)
.map(k => `${k}=${encodeURI(params[k])}`)
.join('&');
async function handleRequest(request) {
const url = new URL(request.url);
// Reject unauthorized origins to avoid wasting API Calls
if (request.headers.get('Origin') !== null && request.headers.get('Origin') !== url.origin && !ALLOWED_ORIGINS.includes(request.headers.get('Origin')) && !ALLOWED_ORIGINS.includes("*")) {
return new Response("{'error': 'Origin not allowed'}", null);
}
let endpoint = url.searchParams.get('endpoint');
if (endpoint == null || endpoint == "") {
return new Response("{'error': 'Missing endpoint'}", null);
}
const re = /{(\w+)}/g;
const params = [...endpoint.matchAll(re)];
const reserved = ["region", "endpoint"];
// Replace path parameters with GET parameters
for (const match of params) {
if (url.searchParams.get(match[1]) == null) {
return new Response(`{'error': 'Missing parameter: ${match[1]}'}`, null);
}
endpoint = endpoint.replace(match[0], encodeURI(url.searchParams.get(match[1])));
reserved.push(match[1]);
}
let region = url.searchParams.get('region');
if (region == null || region == "") {
return new Response("{'error': 'Missing region'}", null);
}
let fullUrl = `https://${region}.api.riotgames.com${endpoint}`;
// Add leftover get parameters
const getParams = {};
for (const [key, value] of url.searchParams) {
if (!reserved.includes(key)) {
getParams[key] = value;
}
}
let reqParams = createQueryParams(getParams);
if (reqParams !== "") {
fullUrl = `${fullUrl}?${reqParams}`;
}
riotRequest = new Request(fullUrl, request);
riotRequest.headers.set('X-Riot-Token', API_KEY);
response = await fetch(riotRequest, {
cf: {
cacheTtl: CACHE_TIME,
cacheEverything: true,
}
});
// Recreate the response so we can modify the headers
response = new Response(response.body, response);
// Set CORS headers
response.headers.set('Access-Control-Allow-Origin', request.headers.get('Origin'));
// Append to/Add Vary header so browser will cache response correctly
response.headers.append('Vary', 'Origin');
return response;
}
// Handle Pre-flight OPTIONS calls for CORS
function handleOptions(request) {
let headers = request.headers;
let origin = "";
if (
headers.get('Origin') !== null &&
headers.get('Access-Control-Request-Method') !== null &&
headers.get('Access-Control-Request-Headers') !== null
) {
if (ALLOWED_ORIGINS.includes(headers.get('Origin')) || ALLOWED_ORIGINS.includes("*")) {
origin = headers.get('Origin');
}
// Handle CORS pre-flight request.
let respHeaders = {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET,HEAD,OPTIONS',
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Headers': request.headers.get('Access-Control-Request-Headers'),
};
return new Response(null, {
headers: respHeaders,
});
} else {
// Handle standard OPTIONS request.
// If you want to allow other HTTP Methods, you can do that here.
return new Response(null, {
headers: {
Allow: 'GET, HEAD, OPTIONS',
},
});
}
}
addEventListener('fetch', event => {
const request = event.request;
const url = new URL(request.url);
if (url.pathname.startsWith(API_ENDPOINT)) {
if (request.method === 'OPTIONS') {
// Handle CORS preflight requests
event.respondWith(handleOptions(request));
} else if (request.method === 'GET' || request.method === 'HEAD') {
// Handle requests to the API server
event.respondWith(handleRequest(request));
} else {
event.respondWith(
new Response(null, {
status: 405,
statusText: 'Method Not Allowed',
})
);
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment