You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
5.0 KiB
151 lines
5.0 KiB
6 months ago
|
import logging
|
||
|
import os
|
||
|
import re
|
||
|
import time
|
||
|
from datetime import datetime
|
||
|
|
||
|
import requests
|
||
|
from flask import Flask, Response, render_template, request, send_from_directory
|
||
|
from prefect.deployments import run_deployment
|
||
|
|
||
|
PORT = 9021
|
||
|
app = Flask(__name__)
|
||
|
|
||
|
logging.basicConfig(level=logging.DEBUG)
|
||
|
|
||
|
|
||
|
def deploy_name():
|
||
|
return datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S") + "Z"
|
||
|
|
||
|
|
||
|
def get_host():
|
||
|
host = os.environ.get("LIGHTNING_CLOUDSPACE_HOST")
|
||
|
if host is None:
|
||
|
default_host = os.environ.get("HOST_NAME", "0.0.0.0")
|
||
|
return f"{default_host}:{PORT}"
|
||
|
else:
|
||
|
return f"{PORT}-{host}"
|
||
|
|
||
|
|
||
|
@app.route("/iframe")
|
||
|
@app.route("/iframe/")
|
||
|
@app.route("/iframe/<path:subpath>")
|
||
|
def home(subpath="images/animations/"):
|
||
|
host = get_host()
|
||
|
initial_url = f"http://{host}/{subpath}"
|
||
|
api_url = f"http://{host}/api"
|
||
|
return render_template(
|
||
|
"index.html", initial_url=initial_url, host=f"http://{host}", api_url=api_url
|
||
|
)
|
||
|
|
||
|
|
||
|
@app.route("/api", methods=["POST"])
|
||
|
def handle_api():
|
||
|
data = request.json # This assumes you're sending JSON data.
|
||
|
url = data.get("url")
|
||
|
if not url.endswith("/"):
|
||
|
url += "/"
|
||
|
|
||
|
logging.debug(f"Received URL: {url}")
|
||
|
params = {"url": url, "limit": 24 * 60, "ext": None}
|
||
|
response = run_deployment(
|
||
|
name="create-animations/noaa-animate",
|
||
|
parameters=params,
|
||
|
flow_run_name=f"{deploy_name()}.webapp.{url}",
|
||
|
)
|
||
|
# response is a FlowRun - need to get what we want from it.
|
||
|
|
||
|
# Process the data as needed.
|
||
|
return {
|
||
|
"status": "success",
|
||
|
"message": f"{url} processed successfully",
|
||
|
# "response": response,
|
||
|
}, 200
|
||
|
|
||
|
|
||
|
@app.route("/videos/<path:filename>")
|
||
|
def custom_static(filename):
|
||
|
return send_from_directory("../out", filename)
|
||
|
|
||
|
|
||
|
@app.route("/", methods=["GET"])
|
||
|
@app.route("/<path:url>", methods=["GET"])
|
||
|
def proxy(url=""):
|
||
|
original_base_url = "https://services.swpc.noaa.gov"
|
||
|
host = get_host()
|
||
|
proxy_base_url = f"http://{host}/"
|
||
|
|
||
|
target_url = f"{original_base_url}/{url}"
|
||
|
logging.debug(f"Fetching URL: {target_url}")
|
||
|
|
||
|
try:
|
||
|
headers = {
|
||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
|
||
|
}
|
||
|
response = requests.get(target_url, headers=headers, stream=True)
|
||
|
excluded_headers = [
|
||
|
"content-encoding",
|
||
|
"content-length",
|
||
|
"transfer-encoding",
|
||
|
"connection",
|
||
|
]
|
||
|
headers = [
|
||
|
(name, value)
|
||
|
for (name, value) in response.raw.headers.items()
|
||
|
if name.lower() not in excluded_headers
|
||
|
]
|
||
|
|
||
|
if "text/html" in response.headers.get("Content-Type", ""):
|
||
|
content = response.content.decode("utf-8")
|
||
|
content = re.sub(r"'http://", "'https://", content)
|
||
|
content = re.sub(
|
||
|
r"https?://services.swpc.noaa.gov", proxy_base_url, content
|
||
|
)
|
||
|
|
||
|
content = content.replace(
|
||
|
"</body>",
|
||
|
f"""
|
||
|
<script>
|
||
|
window.addEventListener('load', function() {{
|
||
|
var hasSufficientImages = false;
|
||
|
var observer = new MutationObserver(function(mutations) {{
|
||
|
mutations.forEach(function(mutation) {{
|
||
|
if (mutation.type === 'childList') {{
|
||
|
console.log('observer');
|
||
|
checkImages();
|
||
|
}}
|
||
|
}});
|
||
|
}});
|
||
|
observer.observe(document.body, {{ childList: true, subtree: true }});
|
||
|
|
||
|
function checkImages() {{
|
||
|
var links = document.querySelectorAll('a');
|
||
|
var imageLinkRegex = /\.(jpg|jpeg|png)(\\?.*)?(#.*)?$/i;
|
||
|
var numImages = Array.from(links).filter(link => imageLinkRegex.test(link.href)).length;
|
||
|
console.log('Number of eligible links:', numImages);
|
||
|
hasSufficientImages = numImages >= 60;
|
||
|
window.parent.postMessage({{ type: 'urlUpdate', url: '{original_base_url}/{url}', eligible: hasSufficientImages }}, '*');
|
||
|
}}
|
||
|
|
||
|
// Run initial check in case content is already loaded
|
||
|
console.log('initial');
|
||
|
checkImages();
|
||
|
}});
|
||
|
</script>
|
||
|
</body>""",
|
||
|
)
|
||
|
content = content.encode("utf-8")
|
||
|
return Response(content, status=response.status_code, headers=headers)
|
||
|
else:
|
||
|
return Response(
|
||
|
response.content, status=response.status_code, headers=headers
|
||
|
)
|
||
|
|
||
|
except Exception as e:
|
||
|
logging.error(f"Error fetching URL: {e}")
|
||
|
return Response(f"Error fetching URL: {e}", status=500)
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
app.run(host="0.0.0.0", port=9021, debug=True)
|