0

I would like to use node.js request module to download a release asset from a private repo. It works fine with the following cURL command:

curl -O -J -L \
     -H "Accept: application/octet-stream" \
https://__TOKEN__:@api.github.com/repos/__USER__/__REPO__/releases/assets/__ASSET_ID__

but it fails when I try using the request module:

var request = require('request');

var headers = {
    'Accept': 'application/octet-stream'
};
var API_URL = "https://__TOKEN__:@api.github.com/repos/__USER__/__REPO__"
var ASSET_ID = __ASSET_ID__

var options = {
    url: `${API_URL}/releases/assets/${ASSET_ID}`,
    headers: headers,
};


function callback(error, response, body) {
    if (error) {
        console.error(error);
    }
    console.log(response.statusCode)
    if (!error && response.statusCode == 200) {
        console.log(body);
    }

    console.log(options.url);
}
var req = request(options, callback);
console.log(req.headers)

I have double checked that the resulting URL when using node is the same as the one I use with cURL.

I receive a 403 statusCode in the response. I do not understand why.

UPDATE: While looking at the headers that are actually sent, I have found that the it uses

{ Accept: 'application/octet-stream',
  host: 'api.github.com',
  authorization: 'Basic __DIFFERENT_TOKEN__' }

I do not understand why the token is changed.

some references: https://gist.github.com/maxim/6e15aa45ba010ab030c4

apairet
  • 3,162
  • 20
  • 23
  • Did you try downloading using cURL _after_ you tried with node and it failed? Is it possible that the resource moved or your token is no longer valid? – Marko Gresak Mar 27 '17 at 15:44
  • I did. It is not a token issue and the resource did not move. – apairet Mar 27 '17 at 15:53
  • Did you inspect the body of 403 response? It might give a clue of what's going on. Also, why are you using `followAllRedirects`? According to [the docs](https://github.com/request/request#requestoptions-callback), that's used to follow non-GET responses, but you are using GET. In your case, you would only need `followRedirect`, which is already `true` by default. – Marko Gresak Mar 27 '17 at 16:04
  • You are right. I updated the question. I also added a note about headers that are actually sent. Weird – apairet Mar 27 '17 at 16:10
  • Irony: the example on `request` page use GitHub and shows how to set the user-agent: https://github.com/request/request#custom-http-headers – apairet Mar 27 '17 at 17:41

1 Answers1

3

GitHub API requires a user agent (https://github.com/request/request#custom-http-headers)

It is also important to set the encoding to null in order to have a buffer and not a string in the body (Getting binary content in Node.js using request)

The working version of the code is thus:

var request = require('request');

var headers = {
    'Accept': 'application/octet-stream',
    'User-Agent': 'request module',
};
var API_URL = "https://__TOKEN__:@api.github.com/repos/__USER__/__REPO__"
var ASSET_ID = __ASSET_ID__

var options = {
    url: `${API_URL}/releases/assets/${ASSET_ID}`,
    headers: headers,
    encoding: null // we want a buffer and not a string
};


function callback(error, response, body) {
    if (error) {
        console.error(error);
    }
    console.log(response.statusCode)
    if (!error && response.statusCode == 200) {
        console.log(body);
    }

    console.log(options.url);
}
var req = request(options, callback);
console.log(req.headers)

Thanks to Marko Grešak.

Community
  • 1
  • 1
apairet
  • 3,162
  • 20
  • 23