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

getArchiveLink() doesn't get the link #391

Open
filiph opened this issue Nov 15, 2023 · 3 comments
Open

getArchiveLink() doesn't get the link #391

filiph opened this issue Nov 15, 2023 · 3 comments

Comments

@filiph
Copy link
Contributor

filiph commented Nov 15, 2023

When calling:

var archiveLink = await github.repositories
    .getArchiveLink(repo, defaultRef, format: 'zipball');

I expect to get the link (String). Instead, the method errors out.

Unhandled exception:
GitHub Error: 
#0      GitHub.handleStatusCode (package:github/src/common/github.dart:486:5)
#1      GitHub.request (package:github/src/common/github.dart:422:7)
<asynchronous suspension>
#2      RepositoriesService.getArchiveLink (package:github/src/common/repos_service.dart:678:22)
<asynchronous suspension>
#3      main (file:///Users/filiph/dev/sample_downloader/bin/sample_downloader.dart:166:21)
<asynchronous suspension>

It turns out that the GitHub API just redirects (?) to the link of the archive, so the call above actually starts downloading the archive itself. The error is because package:github is expecting a JSON response, and so handleStatusCode() throws (the status code is actually 200, it just isn't a JSON).

I'm not sure whether this is an API change on the part of GitHub or what it is.

Expected behavior:
If possible, I'd like to get the URL at which to download the zip/tar archive with a normal (non-authorized) HTTP call, as suggested in the docs. For example, I'd like to pipe the streamed response directly into unzip, or into a temporary file on disk.

If that's not possible, and the only way to access the archive is through an authorized call, then have an API for that, and remove the getArchiveLink() method.

Workaround:

var response = await github.request(
    'GET',
    '/repos/${repo.fullName}/zipball/$defaultRef',
);

This is okay, but breaks encapsulation. Also, it downloads the whole huge file into memory.

Copy link

👋 Thanks for reporting! @robrbecker will take a look.

@robrbecker
Copy link
Member

This appears to be this issue octokit/discussions#12
I'm investigating a couple things:

  • Should the 'request' method take a followRedirects bool to help with this?
  • Should we offer both a getArchive AND a getArchiveLink method to help make things more clear

Any thoughts or preference on these @filiph ?

@filiph
Copy link
Contributor Author

filiph commented Nov 30, 2023

Hi @robrbecker! Sorry for the late reply.

Looking at the other discussion, I'm very much in agreement with octokit/discussions#12 (comment):

Though I understand the Github instructions are "follow all redirects," it just doesn't make a lot of sense for something that is intended to return a big blob vs. 1k of JSON.

I certainly understand our perspectives could be different, though wanted to ring in with mine.

Since some repos are small and others are really not, it's not great to put the whole thing into memory. In Node the way to do getArchive would be to return a Stream, or else to accept a path and write the archive there.

Maybe the stream is the way to go. That wouldn't get in the way of following redirects.

So yes, ideally we'd have:

  • getArchiveLink that just returns the URL
  • getArchive that returns a Stream

I expect many archives to be quite big, so I'd say returning a Stream is much preferable to returning the whole chunk of data. I, for one, want to pipe it directly to the disk.

I'm actually not sure if the URL returned (and redirected to) by getArchiveLink is always public or not. If there's never any auth needed for that link, then there's really no reason to implement getArchive except for convenience. (Not that I'm against convenience — just trying to give you an out if I'm asking too much.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants