#!/usr/bin/env python import os import sys import time import urllib.request import yaml def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) # The key is the url # The value holds the content and the timestamp file_cache = {} file_cache_ttl = 60 mapper_file = '' with open('/var/openfaas/secrets/url-mapper-file', 'r') as f: mapper_file = f.read().strip() def get_url_content(url): if url in file_cache: cache_entry = file_cache[url] if cache_entry['timestamp'] + file_cache_ttl > time.time(): return cache_entry['content'] try: response = urllib.request.urlopen(url) targets = yaml.safe_load(response.read()) except Exception as e: eprint("Failed to load URL mapper file: %s" % e) return None file_cache[url] = { 'content': targets, 'timestamp': time.time() } return targets def get_dict_entry_fallback(d, key, fallback): if key and key in d: return d[key] if key.isnumeric() and int(key) in d: return d[int(key)] if fallback in d: return d[fallback] return d.get('_default', None) def get_entry(args, targets): while args: arg = args.pop(0) if not arg: continue # Fallback to _404 if the key is not found targets = get_dict_entry_fallback(targets, arg, '_404') if isinstance(targets, dict): continue return targets, args # Try to match an index entry return get_dict_entry_fallback(targets, '', '_index'), args def get_entry_for_url(url, args): targets = get_url_content(url) if not targets: return None entry, args = get_entry(args, targets) if not entry: return None if entry.startswith('include:'): entry = entry.split(':', 1)[1] return get_entry_for_url(entry, args) return entry def handle(event, context): args = event.path.split('/') url = get_entry_for_url(mapper_file, args) if not url: return { "statusCode": 404, "body": "URL not found" } return { "statusCode": 302, "body": url, "headers": { "Location": url } }