Skip to content

Commit 18f4dcd

Browse files
committed
add httpx
1 parent c5faf8c commit 18f4dcd

File tree

2 files changed

+21
-36
lines changed

2 files changed

+21
-36
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ requires-python = ">= 3.8"
77
dependencies = [
88
"click>=8.0.0",
99
"fastapi[standard]>=0.109.1", # Minimum safe release (https://osv.dev/vulnerability/PYSEC-2024-38)
10+
"httpx>= 0.28.1",
1011
"pydantic",
1112
"python-dotenv",
1213
"slowapi",
@@ -15,7 +16,6 @@ dependencies = [
1516
"pathspec>=0.12.1",
1617
"typing_extensions>= 4.0.0; python_version < '3.10'",
1718
"uvicorn>=0.11.7", # Minimum safe release (https://osv.dev/vulnerability/PYSEC-2020-150)
18-
"httpx>= 0.28.1",
1919
]
2020

2121
license = {file = "LICENSE"}

src/gitingest/utils/git_utils.py

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
import asyncio
66
import base64
7-
import os
87
import re
98
from typing import Final
109
from urllib.parse import urlparse
1110

11+
import httpx
1212
from starlette.status import (
1313
HTTP_200_OK,
1414
HTTP_301_MOVED_PERMANENTLY,
@@ -115,46 +115,31 @@ async def check_repo_exists(url: str, token: str | None = None) -> bool:
115115
If the host returns an unrecognised status code.
116116
117117
"""
118-
# TODO: use `requests` instead of `curl`
119-
cmd: list[str] = [
120-
"curl",
121-
"--silent", # Suppress output
122-
"--location", # Follow redirects
123-
"--write-out",
124-
"%{http_code}", # Write the HTTP status code to stdout
125-
"-o",
126-
os.devnull,
127-
]
118+
headers = {}
128119

129120
if token and is_github_host(url):
130121
host, owner, repo = _parse_github_url(url)
131122
# Public GitHub vs. GitHub Enterprise
132123
base_api = "https://api.github.com" if host == "github.com" else f"https://{host}/api/v3"
133124
url = f"{base_api}/repos/{owner}/{repo}"
134-
cmd += ["--header", f"Authorization: Bearer {token}"]
135-
136-
cmd.append(url)
137-
138-
proc = await asyncio.create_subprocess_exec(
139-
*cmd,
140-
stdout=asyncio.subprocess.PIPE,
141-
stderr=asyncio.subprocess.PIPE,
142-
)
143-
stdout, _ = await proc.communicate()
144-
145-
if proc.returncode != 0:
146-
return False
147-
148-
status = int(stdout.decode().strip())
149-
if status in {HTTP_200_OK, HTTP_301_MOVED_PERMANENTLY}:
150-
return True
151-
# TODO: handle 302 redirects
152-
if status in {HTTP_404_NOT_FOUND, HTTP_302_FOUND}:
153-
return False
154-
if status in {HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN}:
155-
return False
156-
msg = f"Unexpected HTTP status {status} for {url}"
157-
raise RuntimeError(msg)
125+
headers["Authorization"] = f"Bearer {token}"
126+
127+
async with httpx.AsyncClient(follow_redirects=True) as client:
128+
try:
129+
response = await client.head(url, headers=headers)
130+
status = response.status_code
131+
132+
if status in {HTTP_200_OK, HTTP_301_MOVED_PERMANENTLY}:
133+
return True
134+
# TODO: handle 302 redirects
135+
if status in {HTTP_404_NOT_FOUND, HTTP_302_FOUND}:
136+
return False
137+
if status in {HTTP_401_UNAUTHORIZED, HTTP_403_FORBIDDEN}:
138+
return False
139+
msg = f"Unexpected HTTP status {status} for {url}"
140+
raise RuntimeError(msg)
141+
except httpx.RequestError:
142+
return False
158143

159144

160145
def _parse_github_url(url: str) -> tuple[str, str, str]:

0 commit comments

Comments
 (0)