-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Repository get_contents() 302 redirect no longer functional b/c Github response headers no longer contain status #2125
Description
For the Get Content Repository endpoint: https://docs.github.com/en/rest/reference/repos#get-repository-content
When the the {path} on the endpoint ends with a trailing /, the api responds with a 302 Found and therefore PyGithub must then perform a GET on the url in location response header.
This currently is handled in the below code in PyGithub: https://github.com/PyGithub/PyGithub/blob/master/github/Repository.py#L1824-L1828
# Handle 302 redirect response
if headers.get("status") == "302 Found" and headers.get("location"):
headers, data = self._requester.requestJsonAndCheck(
"GET", headers["location"], parameters=url_parameters
)The issue I am facing with this now is that PyGithub expects there to be a status in the response headers, however the Github api no longer sends status as a response header.
I found this github support community post confirming this change: https://github.community/t/githubs-api-is-not-returning-status-in-its-response-header/160531
See the below cURL commands where I confirmed...
This request returns 200 when I send github as the path
{18:49}~ ➭ curl -I --request GET 'https://api.github.com/repos/PyGithub/PyGithub/contents/github' \
--header 'Authorization: Bearer <token redacted>'
HTTP/2 200
server: GitHub.com
date: Wed, 08 Dec 2021 23:49:06 GMT
content-type: application/json; charset=utf-8
content-length: 198400
cache-control: private, max-age=60, s-maxage=60
vary: Accept, Authorization, Cookie, X-GitHub-OTP
etag: "c4c07fd89012d914782b5cc0b5fc2028374d8a35"
last-modified: Wed, 08 Dec 2021 05:34:29 GMT
x-oauth-scopes: repo, user, workflow
x-accepted-oauth-scopes:
github-authentication-token-expiration: 2022-03-08 23:17:54 UTC
x-github-media-type: github.v3; format=json
x-ratelimit-limit: 5000
x-ratelimit-remaining: 4988
x-ratelimit-reset: 1639009499
x-ratelimit-used: 12
x-ratelimit-resource: core
access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
access-control-allow-origin: *
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
content-security-policy: default-src 'none'
vary: Accept-Encoding, Accept, X-Requested-With
x-github-request-id: DB89:24AF:6CA656:10E89FA:61B14472This request returns 302 when I send github/ as the path
{18:49}~ ➭ curl -I --request GET 'https://api.github.com/repos/PyGithub/PyGithub/contents/github/' \
--header 'Authorization: Bearer <token redacted>'
HTTP/2 302
server: GitHub.com
date: Wed, 08 Dec 2021 23:49:09 GMT
content-type: text/html;charset=utf-8
content-length: 0
location: https://api.github.com/repositories/3544490/contents/github
x-ratelimit-limit: 5000
x-ratelimit-remaining: 4987
x-ratelimit-reset: 1639009499
x-ratelimit-used: 13
x-ratelimit-resource: core
access-control-expose-headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, Deprecation, Sunset
access-control-allow-origin: *
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: origin-when-cross-origin, strict-origin-when-cross-origin
content-security-policy: default-src 'none'
vary: Accept-Encoding, Accept, X-Requested-With
x-github-request-id: DB8A:2115:129B94E:24BBC37:61B14475In both of these cases, we can see there is no status header being returned by Github.
Therefore, when I replicate this function with the trailing / in the path with PyGithub, I get the following error b/c PyGithub fails to perform the necessary redirect since in the above if statement, headers.get("status") == "302 Found" does not return as True.
Python Code
from github import Github
from github import Repository
g = Github("<token redacted>")
repo = g.get_repo("PyGithub/PyGithub")
content = repo.get_contents("github/")Output
Traceback (most recent call last):
File "/Users/webbchawla/Documents/Projects/pygit_tst/main.py", line 10, in <module>
content = repo.get_contents("github/")
File "/Users/webbchawla/Documents/Projects/pygit_tst/.venv/lib/python3.9/site-packages/github/Repository.py", line 1810, in get_contents
return github.ContentFile.ContentFile(
File "/Users/webbchawla/Documents/Projects/pygit_tst/.venv/lib/python3.9/site-packages/github/GithubObject.py", line 283, in __init__
super().__init__(requester, headers, attributes, completed)
File "/Users/webbchawla/Documents/Projects/pygit_tst/.venv/lib/python3.9/site-packages/github/GithubObject.py", line 84, in __init__
self._storeAndUseAttributes(headers, attributes)
File "/Users/webbchawla/Documents/Projects/pygit_tst/.venv/lib/python3.9/site-packages/github/GithubObject.py", line 96, in _storeAndUseAttributes
self._useAttributes(attributes)
File "/Users/webbchawla/Documents/Projects/pygit_tst/.venv/lib/python3.9/site-packages/github/ContentFile.py", line 191, in _useAttributes
if "content" in attributes: # pragma no branch
TypeError: argument of type 'NoneType' is not iterableFor now, I am able to work around this issue by doing .rstrip("/") on the path before calling get_contents() but I figured it would be wise for PyGithub to handle the redirect case as well, however the maintainers feel is the best way.
Let me know if you need any more examples or clarification 😄