Skip to content

Commit d590a75

Browse files
committed
Don't include HTTP headers from GitHub API request in redirected artifact download request
In the use case where the "arduino/report-size-deltas" action is ran from a GitHub Actions workflow triggered by a `schedule` event, it downloads the sketches report file from a workflow artifact. The GitHub REST API is used to perform this artifact download. The artifact download process is: 1. Action sends request to `/repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}` endpoint 2. API responds with HTTP 302 status 3. Action sends request to temporary file download URL provided by the API response 4. Artifact file is downloaded The API request at step (1) must be authenticated using a GitHub access token. This token is passed via the `Authorization` HTTP header in the request. No authentication is required for the download request at step (3). The `urllib.request` Python module is used to perform the HTTP requests. By default, this module passes the headers from the original request to the redirect request. Although these headers were superfluous, they didn't affect the download request when the target artifact was of the v1 format generated by version 3.x and earlier of the "actions/upload-artifact" action. A new v2 artifact format was introduced in the 4.0.0 release of the "actions/upload-artifact" action. Previously, the request at step (3) of the artifact download procedure would fail when the target artifact had the v2 format: ``` urllib.error.HTTPError: HTTP Error 400: Authentication information is not given in the correct format. Check the value of Authorization header. Error: HTTPError: HTTP Error 400: Authentication information is not given in the correct format. Check the value of Authorization header. <?xml version="1.0" encoding="utf-8"?><Error><Code>InvalidAuthenticationInfo</Code><Message>Authentication information is not given in the correct format. Check the value of Authorization header. RequestId:1f13170a-001e-0076-5f5d-4e8d15000000 Time:2024-01-24T00:35:22.8264229Z</Message></Error> ``` The cause of the failure was the inclusion of the `Authorization` HTTP header in the download request. The `urllib.request` Python module can be configured to pass a header in the original request but not in the redirected request by defining the header via the `Request.add_unredirected_header` method instead of in the `Request` instantiation. This provides compatibility for using the action with v2 format artifacts.
1 parent 57289ee commit d590a75

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

reportsizedeltas/reportsizedeltas.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -625,14 +625,11 @@ def raw_http_request(self, url: str, data: bytes | None = None):
625625

626626
logger.info("Opening URL: " + url)
627627

628-
headers = {
629-
"Accept": "application/vnd.github+json",
630-
"Authorization": "Bearer " + self.token,
631-
# GitHub recommends using user name as User-Agent (https://developer.github.com/v3/#user-agent-required)
632-
"User-Agent": self.repository_name.split("/")[0],
633-
"X-GitHub-Api-Version": "2022-11-28",
634-
}
635-
request = urllib.request.Request(url=url, headers=headers, data=data)
628+
request = urllib.request.Request(url=url, data=data)
629+
request.add_unredirected_header(key="Accept", val="application/vnd.github+json")
630+
request.add_unredirected_header(key="Authorization", val="Bearer " + self.token)
631+
request.add_unredirected_header(key="User-Agent", val=self.repository_name.split("/")[0])
632+
request.add_unredirected_header(key="X-GitHub-Api-Version", val="2022-11-28")
636633

637634
retry_count = 0
638635
while True:

reportsizedeltas/tests/test_reportsizedeltas.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,13 @@ def test_raw_http_request(mocker):
876876
token = "test_token"
877877
url = "https://api.github.com/repo/foo/bar"
878878
data = "test_data"
879-
request = "test_request"
879+
880+
class Request:
881+
def add_unredirected_header(self):
882+
pass # pragma: no cover
883+
884+
mocker.patch.object(Request, "add_unredirected_header")
885+
request = Request()
880886
urlopen_return = unittest.mock.sentinel.urlopen_return
881887

882888
report_size_deltas = get_reportsizedeltas_object(repository_name=user_name + "/FooRepositoryName", token=token)
@@ -889,14 +895,16 @@ def test_raw_http_request(mocker):
889895

890896
urllib.request.Request.assert_called_once_with(
891897
url=url,
892-
headers={
893-
"Accept": "application/vnd.github+json",
894-
"Authorization": "Bearer " + token,
895-
"User-Agent": user_name,
896-
"X-GitHub-Api-Version": "2022-11-28",
897-
},
898898
data=data,
899899
)
900+
request.add_unredirected_header.assert_has_calls(
901+
calls=[
902+
unittest.mock.call(key="Accept", val="application/vnd.github+json"),
903+
unittest.mock.call(key="Authorization", val="Bearer " + token),
904+
unittest.mock.call(key="User-Agent", val=user_name),
905+
unittest.mock.call(key="X-GitHub-Api-Version", val="2022-11-28"),
906+
]
907+
)
900908
# URL is subject to GitHub API rate limiting
901909
report_size_deltas.handle_rate_limiting.assert_called_once()
902910

0 commit comments

Comments
 (0)