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:
parent
f422eded7b
commit
4660f5a7ca
2 changed files with 79 additions and 2 deletions
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue