~nhanb/gae-proxy

ref: 0855005fbf7bc0a22f62fb319b08161ecf39da64 gae-proxy/app.py -rw-r--r-- 2.2 KiB
0855005fBùi Thành Nhân easier to use signature 1 year, 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
"""
Dumb (bespoke "protocol" & grossly inefficient) http(s) proxy on Google Cloud Functions.
It also attempts to solve CloudFlare's javascript challenge where necessary.

To use, simply send request to proxy just as you would to the target, but provide some
extra http headers:

- X-Proxy-Key: For authentication.
- X-Proxy-Target-Host: So the proxy knows what hostname to proxy to.
- X-Proxy-Target-Scheme: Optional. Defaults to https.

To deploy:

    $ export GAEPROXY_KEY='my-secret-proxy-key'
    $ gcloud app deploy
"""
import os

import cloudscraper
from flask import Flask, Response, request

http = cloudscraper.create_scraper(
    browser={"browser": "firefox", "platform": "windows", "mobile": False}
)

PROXY_KEY = os.environ["GAEPROXY_KEY"]


app = Flask(__name__)


@app.route("/", defaults={"path": ""}, methods=["GET", "POST", "PUT", "DELETE"])
@app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE"])
def hello_world(path):
    auth_key = request.headers.get("X-Proxy-Key")
    if auth_key != PROXY_KEY:
        return "Go away", 403

    target_headers = {
        key: val
        for key, val in dict(request.headers).items()
        if not (
            key.startswith("X-Appengine-")
            or key
            in (
                "Accept-Encoding",
                "Content-Length",
                "Transfer-Encoding",
                "X-Amzn-Trace-Id",
                "X-Cloud-Trace-Context",
                "X-Forwarded-For",
                "X-Forwarded-Proto",
            )
        )
    }
    target_headers.pop("X-Proxy-Key")
    target_headers.pop("Host")

    target_host = target_headers.pop("X-Proxy-Target-Host")
    target_scheme = target_headers.pop("X-Proxy-Target-Scheme", "https")
    target_path = "/".join(request.full_path.split("/")[1:])
    target_url = f"{target_scheme}://{target_host}/{target_path}"

    send = getattr(http, request.method.lower())
    target_resp = send(target_url, headers=target_headers)

    resp_headers = dict(target_resp.headers)
    resp_headers.pop("Content-Encoding", None)
    resp_headers.pop("Transfer-Encoding", None)

    return Response(
        response=target_resp.content,
        status=target_resp.status_code,
        headers=resp_headers,
    )