Calling Twitter REST api from JavaScript with OAUTH

I’ve started on a project where I need to call Twitter’s REST apis from a Node.js JavaScript app. I’ve built a Java app before that integrated with Twitter, but used a library to help with the OAUTH authentication. Looking around for a JavaScript library, it looks like node-oauth does what I need to do, so gave it a go.

Twitter’s API docs are pretty good, but I ran into an issue with node-oauth with an error coming back from:

POST /statuses/update.json

which returned this message:

{ statusCode: 401,
 data: '{"errors":[{"code":32,"message":"Could not authenticate you."}]}' }

which is odd because using the node-oauth library to authenticate and then call any of the GET apis with node-oauth was working fine. If you Google this error there’s numerous posts about this error for all number of reasons, so I’m not sure it’s a particularly specific message.

Here’s a working example for a GET:

First, use node-oauth to authenticate with your Twitter key, secret, and app access token and secret (which you can set up here):

var oauth = new OAuth.OAuth(
    'https://api.twitter.com/oauth/request_token',
    'https://api.twitter.com/oauth/access_token',
    config.twitterConsumerKey,
    config.twitterSecretKey,
    '1.0A',
    null,
    'HMAC-SHA1'
);

Next, using the returned value from this call, make the GET request (it builds the request including the OAUTH headers for you):

//GET /search/tweets.json
oauth.get(
    'https://api.twitter.com/1.1/search/tweets.json?q=%40twitterapi',
    config.accessToken,
    config.accessTokenSecret,
    function (e, data, res){
        if (e) console.error(e);
        console.log(data);
    });

Attempting a POST to update the status for this account using the similar api:

var status = "{'status':'test 3 from nodejs'}";

oauth.post('https://api.twitter.com/1.1/statuses/update.json',
    config.accessToken,
    config.accessTokenSecret,
    status,
    function(error, data) {
        console.log('\nPOST status:\n');
        console.log(error || data);
});

And this is the call that returned the error about “could not authenticate”.

Looking through a few other tickets for the node-oauth project, this one gave a clue – this particular issue was about special chars in the body content to the POST, but it gave an example of the body formed like this:

var status = ({'status':'test from nodejs'});

I would have thought passing a String would have worked, but I guess the api is expecting an object? Anyway, this is working, and looks good so far.

Serving static content, REST endpoints and Websockets with Express and node.js

I’ve yet to see a framework that is as simple as Express for developing REST endpoints. I’m experimenting with a React app that receives push updates from the server using Websockets. Is it possible to use Express to serve all the requests for this app: static content (the React app), REST endpoints and Websocket? Turns out, yes, and it’s pretty easy too.

Starting first using Express to serve static content:

This uses the static middleware for serving the static content.

Handling REST requests with Express is simple using the get(), post(), put(), and delete() functions on the Router. Adding an example for a GET for /status now we have this:

 

Next, adding support for Websockets, using the ws library. Incrementally adding to the code above, now we create a WebSocket.Server, using the option to pass in the already created HTTP server:

const wss = new SocketServer({ server });

At this point we add callbacks for ‘connection’ and ‘message’ events, and we’re in business:

This is the starting point for a React app to build a websockets client, more on that in a future post. The code so far is available in this github repo: https://github.com/kevinhooke/NodeExpressStaticRESTAndWebsockets

React Flux Store: addChangeListener is not a function

Using React with Flux, you need to register a callback from your Component so that it can be called when the Store emits an event. For an ExampleComponent and ExampleStore, this might look like:

class ExampleComponent extends Component {

    constructor(props) {
        super(props);
    }

    componentWillMount(){
        ChatStore.on('change', this.handleUserNameChange);
    }
...
}

I’ve seen some examples where a helper function is declared in the Store that registers your Component as a listener, so the call from the Component to register with the Store might look like:

    componentWillMount(){
        ChatStore.registerChangeListener(this.handleUserNameChange);
    }

and in your ExampleStore you’ll declare registerChangeListener() (and similar to remove) like this:

addChangeListener(callback) {
    this.on('change', callback);
}

removeChangeListener(callback) {
    this.removeListener('change', callback);
}

All good so far, but here’s the issue I just ran into:

Uncaught TypeError: _ExampleStore2.default.addChangeListener is not a 
function
 at ExampleComponent.componentWillMount (ExampleComponent.jsx:19)
 at ReactCompositeComponent.js:348

Initially this is confusing, since it’s clear we did already declare addChangeListener, so why is this error saying it’s not a function?

The catch is in how we export the Store. The cause of my issue above was that I had exported it like this:

class ExampleStore extends EventEmitter {
..
}
export default ExampleStore;

This is how you would typically export a module but what we’re trying to do is treat the Store as a singleton instance. To do this the export should be:

export default new ExampleStore();

This approach is described in many Flux related articles (here’s an example), but it’s an easy mistake to miss.

JavaScript ES6 default imports vs named imports

I’d been wondering this for a while. What’s the difference between this style of ES6 import:

import A from './A';

vs

import { A } from './A';

I’ve seen and used both, and had guessed that the { A } syntax is when you’re importing a specific named function from a module? I wasn’t convinced this was correct. It turns out the difference is importing a default export, versus importing using a named import.

This is explained here this SO post here:

http://stackoverflow.com/questions/36795819/when-should-i-use-curly-braces-for-es6-import