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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

81 lines
1.9 KiB

import uuid
from urllib.parse import urlsplit
import os
import subprocess
import requests
from flask import Flask, Response, request
from pyhocon import ConfigParser
from requests import Response as RequestsResponse
from werkzeug.routing import Rule
with open("config.conf") as f:
cfg = ConfigParser.parse(f.read())
app = Flask(__name__)
app.url_map.add(Rule("/", endpoint="mirror"))
app.url_map.add(Rule("/<string:path>", endpoint="mirror"))
def unquote(host: str) -> str:
return host.replace('"', "").replace("'", "")
def get_mirror_of(host: str) -> str:
return cfg["site_map"]['"' + unquote(host) + '"']
def get_mirror_url(url: str) -> str:
return url.replace(request.url_root, get_mirror_of(request.url_root))
def search_patch(url: str) -> str:
_us = urlsplit(url)
domain = _us.netloc
path = _us.path
if path == "/":
path = ""
return os.path.abspath(os.path.join(
cfg["patch_dir"],
f"{domain}{path}.patch")
)
def mirrorize_page_content(r: RequestsResponse):
patch_path = search_patch(r.url)
if not (os.path.exists(patch_path) and not os.path.isdir(patch_path)):
return r.content
tmp_file = str(uuid.uuid4())
with open(tmp_file, "w") as f:
f.write(r.text)
patch_proc = subprocess.run(
["patch", tmp_file, patch_path, "-o", "-"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE # hide stderr
)
os.remove(tmp_file)
return patch_proc.stdout
@app.endpoint("mirror")
@app.errorhandler(404)
def mirror(path: str = "/") -> Response:
murl = get_mirror_url(request.url)
r = requests.request(request.method, murl, data=request.data)
return Response(
mirrorize_page_content(r),
status=r.status_code,
content_type=r.headers["Content-Type"],
)
if __name__ == "__main__":
app.run("0.0.0.0", 3131, True)