Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement a /digest/{project_name}/{sha256,blake2b_256}:{file_digest}… #31

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion conveyor/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from aiohttp.web_middlewares import normalize_path_middleware
from aiobotocore.session import get_session as aiobotocore_get_session

from .views import not_found, redirect, health, documentation, documentation_top, index
from .views import not_found, redirect, health, documentation, documentation_top, index, content_sha256, content_blake2b_256
from .tasks import redirects_refresh_task


Expand Down Expand Up @@ -81,6 +81,26 @@ def _cached_aiobotocore_session():
"/packages/{python_version}/{project_l}/{project_name}/{filename}",
redirect,
)
app.router.add_route(
"GET",
"/digest/{project_name}/sha256:{file_sha256}",
content_sha256,
)
app.router.add_route(
"HEAD",
"/digest/{project_name}/sha256:{file_sha256}",
content_sha256,
)
app.router.add_route(
"GET",
"/digest/{project_name}/blake2b_256:{file_blake2b_256}",
content_blake2b_256,
)
app.router.add_route(
"HEAD",
"/digest/{project_name}/blake2b_256:{file_blake2b_256}",
content_blake2b_256,
)
app.router.add_route(
"GET",
"/packages/{tail:.*}",
Expand Down
45 changes: 45 additions & 0 deletions conveyor/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,51 @@ async def _normalize_filename(filename):
return filename


async def content_by_hash(request, digest=None, file_digest=None):
project_name = request.match_info["project_name"]
json_url = urllib.parse.urljoin(
request.app["settings"]["endpoint"],
"/pypi/{}/json".format(project_name),
)

async with request.app["http.session"].get(json_url) as resp:
if 400 <= resp.status < 500:
return web.Response(status=resp.status)
elif 500 <= resp.status < 600:
return web.Response(status=503)

# It shouldn't be possible to get a status code other than 200 here.
assert resp.status == 200

# Get the JSON data from our request.
data = await resp.json()

# Look at all of the files listed in the JSON response, and see if one
# matches our filename and Python version. If we find one, then return a
# 302 redirect to that URL.
for release in data.get("releases", {}).values():
for file_ in release:
if file_['digests'][digest] == file_digest:
return web.Response(
status=302,
headers={
"Location": file_["url"],
"Cache-Control": "max-age=604800, public",
},
)

# If we've gotten to this point, it means that we couldn't locate an url
# to redirect to so we'll jsut 404.
return web.Response(status=404, headers={"Reason": "no file found"})


async def content_sha256(request):
return await content_by_hash(request, digest="sha256", file_digest=request.match_info["file_sha256"])

async def content_blake2b_256(request):
return await content_by_hash(request, digest="blake2b_256", file_digest=request.match_info["file_blake2b_256"])


async def redirect(request):
python_version = request.match_info["python_version"]
project_l = request.match_info["project_l"]
Expand Down
Loading