feat: add proxy for Git client requests to GitHub

Introduced a new route to handle Git client requests, proxying them to GitHub. This includes support for methods like GET, POST, PUT, DELETE, and PATCH. Added the `requests` library to manage the HTTP requests and updated imports accordingly.

This enhancement allows Git client interactions with the app to be seamlessly redirected to corresponding GitHub repositories, improving integration and user experience.
This commit is contained in:
Kumi 2024-06-19 11:49:34 +02:00
parent f422eded7b
commit 4660f5a7ca
Signed by: kumi
GPG key ID: ECBCC9082395383F
2 changed files with 79 additions and 2 deletions

View file

@ -15,7 +15,7 @@ classifiers = [
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
]
dependencies = ["dulwich", "flask", "markdown2[all]"]
dependencies = ["dulwich", "flask", "markdown2[all]", "requests"]
[project.scripts]
gitcloak = "gitcloak.app:main"

View file

@ -1,4 +1,13 @@
from flask import Flask, render_template, abort, send_from_directory, Response
from flask import (
Flask,
render_template,
abort,
send_from_directory,
Response,
request,
redirect,
)
import requests
from .classes.git import Git
from .classes.markdown import RelativeURLRewriter
import logging
@ -206,6 +215,74 @@ def preview_file(owner: str, repo: str, file_path: str):
abort(404, description=str(e))
@app.route("/<path:subpath>.git", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
@app.route(
"/<path:subpath>.git/<path:extra>",
methods=["GET", "POST", "PUT", "DELETE", "PATCH"],
)
def proxy_git(subpath, extra=None):
"""Route for proxying Git client requests to GitHub.
Args:
subpath (str): The subpath of the request.
extra (str): An optional extra path after .git.
Returns:
Response: A response from the repository on GitHub.
"""
path = f"{subpath}.git"
if extra:
path += f"/{extra}"
github_url = f"https://github.com/{path}"
logger.debug(f"Proxying Git request to {github_url}")
resp = requests.request(
method=request.method,
url=github_url,
headers={
key: value
for (key, value) in request.headers.items()
if key.lower() != "host"
and not key.lower().startswith("x-forwarded")
and not key.lower().startswith("forwarded")
},
data=request.get_data(),
cookies=request.cookies,
params=request.args,
allow_redirects=False,
stream=True,
)
# Those headers shouldn't be passed directly to the client
excluded_headers = [
"content-length",
"content-encoding",
"transfer-encoding",
"connection",
]
headers = [
(name, value)
for (name, value) in resp.raw.headers.items()
if name.lower() not in excluded_headers
]
return Response(resp.raw, status=resp.status_code, headers=dict(headers))
@app.before_request
def catch_git_requests():
if "git/" in request.headers.get("User-Agent", ""):
try:
path = request.path.lstrip("/")
path = path.split("/")
return proxy_git("/".join(path[:2]), "/".join(path[2:]) or None)
except Exception as e:
logger.error(f"Error proxying Git request: {e}")
abort(404, description=str(e))
def main():
"""Main function to run the Flask app."""
port = os.environ.get("PORT", 8107)