-
Notifications
You must be signed in to change notification settings - Fork 67
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
Cannot download private release asset #12
Comments
This comment was marked as outdated.
This comment was marked as outdated.
I fear it doesn’t work for a similar reason as https://github.com/octokit/rest.js/issues/758, the CORS headers configured on GitHub’s S3 are probably not allowing for direct downloads in browsers from other domains. Can you try to not set the custom header so that you can retrieve the Let me know if that works |
I tried this code but I am not sure about the
Here is the response
|
As this is in the browser, would it be a redirection to just redirect to I’ll look more into it, I’m curious where exactly the problem lies, but it’s most likely a problem with CORS settings on Amazon. Could you explain your use case why you need to download the asset in the browser? I’m trying to build a case to have these CORS headers added, knowing your use case will help :) |
I am building an electron app with a plugin system. Theses plugins use custom native node modules. These modules are already compiled and released as in a Github release asset (one for each platform: windows, linux, mac). My goal is to automatically download these "ready to go" assets from the plugin. |
I’m not very familiar with Electron, but I don’t think it should be affected by CORS limitations as its a native app? Could you maybe create a repository with a minimal electron app to reproduce the problem? And could you test it against a public repository? Does it work there? |
It works with a public repository. I must have my headers wrong. |
In fetch you’d pass the personal access token like this
|
Ok, so I tried this code
Here the response
The same token is used with octokit and it works to call the github API. |
@gr2m Any idea of why it does not work? Are you able to reproduce this issue? |
I was able to reproduce the problem. I’ve created a test repository and invited you to it: I have no workaround I’m afraid. This is a limitation with the CORS settings on GitHub’s S3 as far as I can tell. I’ll investigate some more and then bring it up with GitHub’s support/security team. There are a few other use cases where missing CORS settings is a problem for usage in browser: https://github.com/octokit/rest.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22blocked+by+api%22 |
Looks like this does not throw an error const assetUrl = https://api.github.com/repos/gr2m/octokit-rest.js-1417/releases/assets/13689345
const token = 'your token here'
const response = await fetch(`${assetUrl}?access_token=${token}`, {
headers: {
accept: 'application/octet-stream'
},
mode: 'no-cors'
}) but |
@gr2m any update or news from GitHub’s support/security team? |
I’ll bring it up tomorrow in a meeting, I’ll keep you posted here. |
Any feedback from your meeting? |
Don't expect this to be resolved anytime soon. I will update this issues as soon as there are any news. |
Any news? |
Unfortunately no. The only thing you can do right now is to inform support@github.com that this is a blocking issue for you to bump the priority on the problem internally. |
@gr2m any update? Github is deprecating the workarround with |
No :( I've let them know but didn't hear back. I'll have a call with some folks of the API team tomorrow and will bring it up directly, I'll keep you posted |
Hello @gr2m, any update on this? |
I promise that as soon as there is an update I will post it here. For the time being, the best you can do is to contact support at https://support.github.com/contact and let them know about your use case. They are aware of the problem, but the more people report it and share their use cases, the higher the priority will get. Thank you all for your patience and support |
Hi, have you tried with: request(
{
url:
"https://api.github.com/repos/:owner/:repo/releases/assets/:asset_id",
method: "GET",
headers: {
Accept: "application/octet-stream",
Authorization: "token " + process.env.GITHUB_TOKEN,
"User-Agent": "",
},
},
function (error, response, body) {
console.log(body);
}
); The You can do it also with curl -v -L -H 'Accept: application/octet-stream' -H 'Authorization: token YOUR_TOKEN' https://api.github.com/repos/:owner/:repo/releases/assets/:asset_id |
This won't for private assets that redirect to s3. AWS complains that the Authorization header is present. You can use the query param to work around this, but it looks like that support is being deprecated. |
I'm using the above code to retrive private assets that redirect to S3 and it works for me. The In the nodeJS part, "User-Agent": "" because without you get this error: Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes. Have you try it? Let me know. |
Not working for me either with private repos. |
No update. But I created a dedicated repository for GitHub API limitations, including the use cases that GitHub users have for them. I hope that will help with the decision making on GitHub's site. Please add your use cases to https://github.com/gr2m/github-api-wishlist/tree/master/wishlist/cors-for-adjacent-domains |
Thanks @edospadoni for the hint! For now, we have to download assets from private repos via plain HTTP calls outside Octokit. I use got for the HTTP call - // TypeScript implementation:
import got from "got";
import { pipeline } from "stream";
import { createWriteStream } from "fs";
import { promisify } from "util";
const asyncPipeline = promisify(pipeline);
type TDownload = {
owner: string;
repo: string;
assetId: number;
toLocalFile: string;
githubToken?: string;
};
export async function downloadGithubAsset(dl: TDownload) {
const token = dl.githubToken || process.env.GITHUB_TOKEN;
return asyncPipeline(
got.stream(
`https://api.github.com/repos/${dl.owner}/${dl.repo}/releases/assets/${dl.assetId}`,
{
method: "GET",
headers: {
Accept: "application/octet-stream",
Authorization: `token ${token}`,
"User-Agent": "",
},
}
),
createWriteStream(dl.toLocalFile)
);
} |
Based on https://developer.github.com/changes/2020-02-10-deprecating-auth-through-query-param/, My understanding is that a part of the issue is that I imagine in ideal case the fix would be on server-side so that My use case is downloading private assets at a Next.js site and then serving them through it. I'm publishing private fonts this way by using GitHub releases as a registry and Next.js as my proxy. |
For what it's worth, here's an Axios based solution that seems to work: async function getAsset(url) {
const response = await axios.get(url, {
headers: {
Accept: "application/octet-stream",
Authorization: `token ${process.env.GITHUB_TOKEN}`,
"User-Agent": ""
},
responseType: "arraybuffer"
});
return response.data;
} It expects an url from an asset object gained through GitHub API as a parameter. |
You can also use const requestOptions = octokit
.request.endpoint("GET /repos/:owner/:repo/releases/assets/:asset_id", {
headers: {
Accept: "application/octet-stream"
},
owner,
repo,
asset_id
}); to get generic request options (except the |
@gr2m no chance there's a ETA or any sort of timeline on this issue? It's causing real pain for my users |
Sorry, I'm not aware of any movement on this, unfortunately. Maybe @nickfloyd can check, but as this has been open for so long, I wouldn't get my hopes up. |
any solution ?
|
Here's a working solution, best of luck all. 👍 const { Octokit } = require("octokit");
const { Readable } = require('stream');
const fs = require('fs'); // For file operations
const github_pat = 'some-pat-token';
async function downloadAsset(id, repo, fileName) {
const opts = octokit.request.endpoint('GET /repos/{owner}/{repo}/releases', {
headers: {
Accept: "application/octet-stream",
Authorization: `token ${github_pat}`
},
owner: 'some-owner',
repo
})
const response = await fetch(`https://api.github.com/repos/some-owner/${repo}/releases/assets/${id}`, { headers: opts.headers });
if (!fs.existsSync('downloads')) {
fs.mkdirSync('downloads');
}
if (!response || !response.status === 200) {
return { status: false, message: `Failed to download asset ${fileName}` };
}
const body = Readable.fromWeb(response.body);
const download_write_stream = fs.createWriteStream(`downloads/${fileName}`);
body.pipe(download_write_stream);
return new Promise((resolve) => {
download_write_stream.on('finish', () => {
return resolve({ status: true, message: `Downloaded - ${fileName}` });
});
download_write_stream.on('error', (err) => {
console.log(err);
return resolve({ status: false, message: `Failed to Download - ${fileName}` });
});
})
} |
Here is the magic required to stream release assets to a file using rest.js, typescript, and async/await: import { Octokit } from "@octokit/rest";
import { createWriteStream } from "node:fs";
import { join } from "node:path";
import { pipeline } from "node:stream/promises";
async function fetchAsset() {
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const asset = await octokit.rest.repos.getReleaseAsset({
owner: "foxglove",
repo: "app",
asset_id: 12345,
headers: {
accept: "application/octet-stream",
},
request: {
parseSuccessResponseBody: false, // required to access response as stream
},
});
const assetStream = asset.data as unknown as NodeJS.ReadableStream;
const outputFile = createWriteStream(join("outputdir", "file.zip"));
await pipeline(assetStream, outputFile);
} |
I think we completely forgot about the return type to account for the |
Yeah, the return type is a problem even without the streaming option too. TypeScript thinks it’s a normal shaped response object, but instead it returns an ArrayBuffer iirc. |
I am trying to download an asset from Github. Here is the corresponding code:
I got this error in return:
What do I have to add to my headers to make it works?
Thanks for your help!
The text was updated successfully, but these errors were encountered: