Skip to content

Latest commit

 

History

History
68 lines (54 loc) · 2.14 KB

proxy-flask.md

File metadata and controls

68 lines (54 loc) · 2.14 KB

Proxy DataGoat with Flask

Read the proxy rules first.

import os
import requests
from flask import Flask, Response, request
from werkzeug.middleware.proxy_fix import ProxyFix

COLLECTOR = os.environ.get("DATAGOAT_HOST", "https://datagoat.yourname.workers.dev")

app = Flask(__name__)
# Behind one load balancer or reverse proxy: trust its X-Forwarded-For so remote_addr is the visitor.
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)

_script_cache = {"body": None}


def forward_headers():
    prior = request.headers.get("X-Forwarded-For")
    headers = {
        "User-Agent": request.headers.get("User-Agent", ""),
        "X-Real-IP": request.remote_addr or "",
        "X-Forwarded-For": f"{prior}, {request.remote_addr}" if prior else (request.remote_addr or ""),
    }
    if request.headers.get("Sec-GPC"):
        headers["Sec-GPC"] = request.headers["Sec-GPC"]
    return headers


@app.get("/js/script.js")
def datagoat_script():
    if _script_cache["body"] is None:
        upstream = requests.get(f"{COLLECTOR}/js/script.js", headers=forward_headers(), timeout=5)
        upstream.raise_for_status()
        _script_cache["body"] = upstream.content
    return Response(
        _script_cache["body"],
        mimetype="application/javascript",
        headers={"Cache-Control": "public, max-age=3600"},
    )


@app.post("/api/events")
def datagoat_events():
    headers = forward_headers()
    headers["Content-Type"] = request.content_type or "text/plain"
    upstream = requests.post(
        f"{COLLECTOR}/api/events", data=request.get_data(), headers=headers, timeout=5
    )
    return Response(
        upstream.content,
        status=upstream.status_code,
        content_type=upstream.headers.get("Content-Type", "application/json"),
        headers={"Cache-Control": "no-store"},
    )

The in-process script cache lives until the worker restarts; use Flask-Caching with a one-hour timeout if you want it to refresh by itself. If Flask-WTF's CSRF protection is on, exempt datagoat_events.

Script tag:

<script defer data-website-id="dgid_XXXXXXXXXXXXXXXX" data-domain="example.com" src="/js/script.js"></script>