Something went wrong. Try again.
🌉 A bridge between decentralized social networks fed.brid.gy
Something went wrong. Try again.
bridgy-fed flask_app.py
3.9 kB · 115 lines
Python
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116"""Flask application for frontend.
app.py has the full app with all modules imported. This is separate so thatwe can import it in those modules without causing a circular import."""import jsonimport loggingfrom pathlib import Pathimport sysfrom urllib.parse import urljoin
import arroba.serverfrom arroba import xrpc_identity, xrpc_actor, xrpc_repo, xrpc_server, xrpc_syncfrom flask import Blueprint, Flask, g, requestfrom werkzeug.middleware.proxy_fix import ProxyFixfrom google.api_core.exceptions import PermissionDeniedfrom lexrpc.server import Redirect, Serverimport oauth_dropinsfrom webutil import ( appengine_info, appengine_config, flask_util,)
import common
logger = logging.getLogger(__name__)logging.getLogger('negotiator').setLevel(logging.WARNING)
app_dir = Path(__file__).parent
app = Flask(__name__, static_folder='static')app.template_folder = './templates'app.json.compact = Falseapp.config.from_pyfile(app_dir / 'config.py')app.url_map.converters['regex'] = flask_util.RegexConverterapp.after_request(flask_util.default_modern_headers)app.post(flask_util.CSP_REPORT_PATH)(flask_util.csp_report)
# quick and dirty WAF, so that we don't incur the complexity and cost of using# a GCP LB and Cloud Armor## blocking abusive bots that ignore robots.txt. these replace the IP blocks we had in# the App Engine firewall before this service moved to Cloud Run.## TODO: move to datastore with webutil.models.Reloader?# TODO: move to GCP ALBBLOCKED_CIDRS = ( # '2a03:2880::/32', # Meta/Facebook # '57.141.0.0/16', # Meta/Facebook)BLOCKED_USER_AGENTS = ( 'meta-externalagent',)app.before_request(flask_util.block(cidrs=BLOCKED_CIDRS, user_agents=BLOCKED_USER_AGENTS))
app.register_error_handler(Exception, flask_util.handle_exception)app.register_error_handler(PermissionDenied, flask_util.handle_read_only_permission_denied)
od_path = Path(oauth_dropins.__file__).parentapp.register_blueprint(Blueprint( 'oauth_dropins_static', __name__, static_folder=od_path / 'static', static_url_path='/oauth_dropins_static'))app.register_blueprint(Blueprint( 'oauth_dropins_fonts', __name__, static_folder=od_path / 'fonts', static_url_path='/fonts'))
@app.get('/.well-known/security.txt')def security_txt(): return app.send_static_file('security.txt')
@app.get('/<any(favicon.ico,robots.txt):filename>')def static_file(filename): return app.send_static_file(filename)
# don't redirect API requests with blank path elementsapp.url_map.merge_slashes = Falseapp.url_map.redirect_defaults = False
ndb_context_kwargs = { **common.NDB_CONTEXT_KWARGS, 'cache_policy': lambda key: False,}app.wsgi_app = flask_util.ndb_context_middleware( app.wsgi_app, client=appengine_config.ndb_client, **ndb_context_kwargs)
# make Flask's request info (request.url etc) reflect the actual end user's HTTP# request (https, host, etc), based on X-Forwarded-* etc headers## https://docs.cloud.google.com/functions/docs/reference/headers# https://werkzeug.palletsprojects.com/en/stable/middleware/proxy_fix/app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_for=1)
# we don't support password login. atproto_oauth implements getSession on OAuth.for nsid in ( 'com.atproto.server.createSession', 'com.atproto.server.refreshSession',): del arroba.server.server._methods[nsid]
@arroba.server.server.method('com.atproto.sync.getRepo', override=True)def get_repo(input, **kwargs): """Redirects to Hubble, since getRepo is too expensive for us to serve.
https://github.com/snarfed/arroba/issues/93 """ if request.headers.get('Authorization'): return xrpc_sync.get_repo(input, **kwargs)
raise Redirect( urljoin('https://bridgy-hubble.microcosm.blue/', request.full_path), status=302)