5

I am trying to get JSON data for a Trello board using the following URL, using Node.js's https module:

https://trello.com/b/nC8QJJoZ.json

Here's my code:

var https = require('https');

https.get('https://trello.com/b/nC8QJJoZ.json', function (res) {
    console.log('statusCode:', res.statusCode);
    console.log('headers:');
    console.log(res.headers);
    res.setEncoding('utf8');

    res.on('data', function (chunk) {
        console.log(chunk);
    });
}).on('error', function (e) {
    console.log('ERROR: ' + e);
});

Although the URL works perfectly in browser, It returns a body containing the string "invalid key", with a 401 status. Following is the output:

statusCode: 401
headers:
{ 'cache-control': 'max-age=0, must-revalidate, no-cache, no-store',
  'x-content-type-options': 'nosniff',
  'strict-transport-security': 'max-age=15768000',
  'x-xss-protection': '1; mode=block',
  'x-frame-options': 'DENY',
  'x-trello-version': '1.430.0',
  'x-trello-environment': 'Production',
  'set-cookie':
   [ 'dsc=ae78a354044f982079cd2b5d8adc4f334cda679656b3539ee0adaaf019aee48e; Path=
     'visid_incap_168551=/NYMaLRtR+qQu/H8GYry1BCKl1UAAAAAQUIPAAAAAAC1zWDD1JLPowdC
     'incap_ses_218_168551=+/2JSB4Vz0XJO/pWbX4GAxCKl1UAAAAA0pAbbN5Mbs4tFgbYuskVPw
  expires: 'Thu, 01 Jan 1970 00:00:00',
  'content-type': 'text/plain; charset=utf-8',
  'content-length': '12',
  etag: 'W/"c-b1ec112"',
  vary: 'Accept-Encoding',
  date: 'Sat, 04 Jul 2015 07:24:00 GMT',
  'x-iinfo': '1-11281210-11279245 PNNN RT(1435994639565 404) q(0 0 0 -1) r(3 3) U
  'x-cdn': 'Incapsula' }
invalid key

What am I doing wrong?

sampathsris
  • 21,564
  • 12
  • 71
  • 98

1 Answers1

4

Well, it turns out that we need to provide a Trello API application key (generated from here) with our request.

var https = require('https');
var KEY = '<replace this with your app key>';

https.get('https://trello.com/b/nC8QJJoZ.json?key=' + KEY, function (res) {
    ...
});

This seems to me a weird requirement because we are not using Trello's API endpoint. (Even if I solved the problem, I would still like to know why a browser can access the resource, but a server side script cannot.)

sampathsris
  • 21,564
  • 12
  • 71
  • 98
  • It may not look like it, but we handle that as being part of our API. Requests that look like they're coming from a browser and are for public resources are exempted from the app key requirement, so that public boards load correctly. – Aaron Dufour Jul 07 '15 at 02:59
  • "Requests that **look like they're coming from a browser**". Oooooooooh! I think I might know what to do. @AaronDufour, I think you should restrict usage on things like requests per IP inside a temporal window. It's not hard to forge a request to look like it's coming from a browser. – sampathsris Jul 07 '15 at 03:26
  • We do rate limit by IP. You should just pass an app key. Why do you think forging a browser request is a better solution? – Aaron Dufour Jul 07 '15 at 04:10
  • @AaronDufour: I don't necessarily think forging a browser request is *better*. But someone *can* do it. I'll try it for science but I'm definitely not doing it on my app. – sampathsris Jul 07 '15 at 10:15
  • I'm trying to embed a Trello board in a page for personal use. But `/b/nC8QJJoZ.html` or `/b/nC8QJJoZ.js` are useless for me because they don't get instantly updated. So I created a simple angular app which uses `/b/nC8QJJoZ.json`. But `/b/nC8QJJoZ.json` does not support CORS. And I can't embed a Trello app key in my angular app; I don't want users to see the key. So I'm forced to make a simple proxy to get the JSON and serve it to my app. That's how I encountered the problem. – sampathsris Jul 07 '15 at 10:17
  • 1
    App keys are not necessarily secret. Most client apps expose them. I wouldn't worry about it. If you want CORS, you should use the `/1/` API - `/b/:id.json` just makes a call into the API with particular arguments. – Aaron Dufour Jul 07 '15 at 17:11