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

Parse Github Asset Based on Accessibility #77

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jacderida
Copy link

@jacderida jacderida commented Nov 6, 2021

For supporting private releases, the ReleaseAsset parsing function was changed to use a different field in the JSON document, namely from browser_download_url -> url. This change breaks the download of assets for public Releases, as those still use the previous field.

You can see this in the documentation for the API: https://docs.github.com/en/rest/reference/repos#releases

On a public release, the 'url' field on the asset doesn't return the download location for the asset, so the download_url for the
ReleaseAsset struct isn't set correctly.

This change introduces an is_private parameter on the from_asset function set the field based on whether the release is private or not. It's determined to be private based on whether an auth token has been specified.

For supporting private releases, the ReleaseAsset parsing function was
changed to use a different field in the JSON document, namely from
browser_download_url -> url. This change breaks the download of assets
for public Releases, as those still use the previous field.

You can see this in the documentation for the API:
https://docs.github.com/en/rest/reference/repos#releases

On a public release, the 'url' field on the asset doesn't return the
download location for the asset, so the download_url for the
ReleaseAsset struct isn't set correctly.

This change introduces an 'is_private' parameter on the from_asset
function set the field based on whether the release is private or not.
It's determined to be private based on whether an auth token has been
specified.
@jaemk
Copy link
Owner

jaemk commented Nov 8, 2021

@jacderida Thanks for pointing this out. I see what you're saying, and I see that running the github example says it's going to download from the "asset" url instead of from the actual "download" url e.g.

 cargo run --example github --features "archive-tar archive-zip compression-flate2 compression-zip-deflate"
 
 ...
 Checking target-arch... x86_64-apple-darwin
Checking current version... v0.27.0
Checking latest released version... v9.9.10
New release found! v0.27.0 --> v9.9.10
New release is *NOT* compatible

github release status:
  * Current exe: "/Users/james/dev/self_update/target/debug/examples/github"
  * New exe release: "self_update-v9.9.10-x86_64-apple-darwin.tar.gz"
  * New exe download url: "https://api.github.com/repos/jaemk/self_update/releases/assets/9719319"

And then curling that url directly just returns json

curl -L https://api.github.com/repos/jaemk/self_update/releases/assets/9719319 
{"url":"https://api.github.com/repos/jaemk/self_update/releases/assets/9719319","id":9719319,"node_id":"MDEyOlJlbGVhc2VBc3NldDk3MTkzMTk=","name":"self_update-v9.9.10-x86_64-apple-darwin.tar.gz","label":"","uploader":{"login":"jaemk","id":13563490,"node_id":"MDQ6VXNlcjEzNTYzNDkw","avatar_url":"https://avatars.githubusercontent.com/u/13563490?v=4","gravatar_id":"","url":"https://api.github.com/users/jaemk","html_url":"https://github.com/jaemk","followers_url":"https://api.github.com/users/jaemk/followers","following_url":"https://api.github.com/users/jaemk/following{/other_user}","gists_url":"https://api.github.com/users/jaemk/gists{/gist_id}","starred_url":"https://api.github.com/users/jaemk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jaemk/subscriptions","organizations_url":"https://api.github.com/users/jaemk/orgs","repos_url":"https://api.github.com/users/jaemk/repos","events_url":"https://api.github.com/users/jaemk/events{/privacy}","received_events_url":"https://api.github.com/users/jaemk/received_events","type":"User","site_admin":false},"content_type":"application/gzip","state":"uploaded","size":1508298,"download_count":91,"created_at":"2018-11-16T05:09:22Z","updated_at":"2018-11-16T05:09:22Z","browser_download_url":"https://github.com/jaemk/self_update/releases/download/v9.9.10/self_update-v9.9.10-x86_64-apple-darwin.tar.gz"}

Now.. what's baffling me is that the github example still "works"... when I run it, it does download the actual release, unpackages it, and overwrites my ./target/debug/examples/github with the executable that was uploaded back in 2018... Any ideas?

@jacderida
Copy link
Author

jacderida commented Nov 9, 2021

Hmm, that's strange indeed. I'm honestly not sure. What we were seeing was the JSON document being downloaded rather than the actual asset.

To be honest, I did want to do some more testing before I submitted the PR to you. The commit where the field was changed from browser_download_url was to support private repositories. I was just working under the assumption that since the field was changed when implementing functionality related to private releases, then for a private release, the API set the URL for the asset to the url field rather than browser_download_url. Otherwise I couldn't see a reason for the change.

I didn't get time to validate that assumption, though. I guess it's possible that GIthub maybe changed the field at some point, but they changed it back again?

We are trying to publish one of our crates that use this one and right now it's using a git reference for this dependency which contains my fix. So I just didn't quite have time to do any more elaborate testing, sorry.

@jaemk
Copy link
Owner

jaemk commented Nov 9, 2021

Ah, I see why it's working - when you send an accept: application/octet-stream in the request github will return the asset's content instead of the info as json:

curl -Lv \
    -H 'accept: application/octet-stream' \
    https://api.github.com/repos/jaemk/self_update/releases/assets/9719319 \
    -o download.tar.gz \
    && tar -xf download.tar.gz \
    && ./github

And the request here just happens to automatically set an accept header:

.headers(headers)

(I added a couple printlns to check if there were any other headers being sent):

github release status:
  * Current exe: "/Users/james/dev/self_update/target/debug/examples/github"
  * New exe release: "self_update-v9.9.10-x86_64-apple-darwin.tar.gz"
  * New exe download url: "https://api.github.com/repos/jaemk/self_update/releases/assets/9719319"

The new release will be downloaded/extracted and the existing binary will be replaced.
Do you want to continue? [Y/n]
Downloading...
REQ: https://api.github.com/repos/jaemk/self_update/releases/assets/9719319 -> {"accept": "application/octet-stream", "user-agent": "rust-reqwest/self-update"}

So I think the simpler move would be to explicitly add an accept: application/octet-stream in the request instead of relying on reqwest to set it implicitly (not sure why it even does) and instead of making the download-url-key dynamic

@jacderida
Copy link
Author

OK, thanks. However, I'm not quite sure what the way forward is here. Would you like me to close this PR and open another one? Or were you going to make that change?

@jaemk
Copy link
Owner

jaemk commented Nov 9, 2021

Either or - You could do it here or in a new PR, up to you

@jacderida
Copy link
Author

Sorry for taking so long to get back to you. Lots of work got in the way.

I was just about to address this. If I understand you correctly, you're asking me to change the code to add the application/octet-stream header?

However, this is already being done here: https://github.com/jaemk/self_update/blob/master/src/update.rs#L217

It also shows that header as set in the output on your post. I think I've possibly misunderstood something. Could you advise please?

@jaemk
Copy link
Owner

jaemk commented Dec 15, 2021

hm, yeah sorry I missed that - guess everything's all set already

@jacderida
Copy link
Author

Given we still experience the problem with the incorrect URL, where does that leave us?

@jaemk
Copy link
Owner

jaemk commented Dec 15, 2021

Interesting. Can you confirm (or share a link to your release) whether curling your release with an -H 'accept: application/octet-stream' and the asset["url"] still results in a json document being downloaded?

@jacderida
Copy link
Author

Sorry for taking some time to get back to you.

So I found the problem. We had been using your crate not just for updating the current crate, but also for downloading assets from releases for other crates. Here's the code we were using:

self_update::Download::from_url(&asset.download_url)
         .show_progress(true)
         .download_to(&tmp_tarball)
         .wrap_err_with(|| format!("Error downloading release asset '{}'", asset.download_url))?;

So the problem was, the octet-stream header wasn't being included at this point. I've since replaced this code with something else, but if we were still using it, we could modify it on our end to set the header. I notice you've done that in an example.

I personally think it would be a better API if this header was set in download_to, as then the caller doesn't need to be aware of it, but I'm not sure you would agree. I can submit a modification for that, or if you don't agree, you can feel free to just close the PR.

@jaemk
Copy link
Owner

jaemk commented Jan 8, 2022

Ah, I see. Yes, I agree that it would be better if the header was set automatically. Could you make that change here or in a new PR?

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

Successfully merging this pull request may close these issues.

2 participants