2

I'm trying to make a text post to Tumblr using their API and chrome_ex_oauth.

The whole process of getting authorized works. What I can't get to work is doing a POST. I'm doing the following:

Edit: I've updated the code to reflect Rob W's correct suggestion about the body field

var stringify = function (parameters) {
  var params = [];
  for(var p in parameters) {
    params.push(encodeURIComponent(p) + '=' +
                encodeURIComponent(parameters[p]));
  }
  return params.join('&');
};

var onAuthorized = function() {
  var url = 'http://api.tumblr.com/v2/blog/jindie.tumblr.com/post';
  var request = {
    'method': 'POST',
    'headers':{
      'Content-Type':'application/x-www-form-urlencoded'
    },
    'body': stringify({
      'type': 'text',
      'state': 'draft',
      'title': 'Test post...',
      'body': 'Hello, World!'
    })
  };

  oauth.sendSignedRequest(url, function(responseText, xhr){alert(responseText);}, request);
};

oauth.authorize(onAuthorized);

I've been examining the code, and thinking what could be wrong, but I seriously have no idea. Do you?

Do you know where I'm going wrong?

Nakilon
  • 34,866
  • 14
  • 107
  • 142
Sparragus
  • 883
  • 1
  • 9
  • 24

1 Answers1

3

When the documentation doesn't help have a look at the source code, chrome_ex_oauth.js.

You have to use 'body' instead of 'parameters':

var request = {
  'method': 'POST',
  'body': {

Debugging

In order to find the cause, I followed these steps (annotated my thoughts):

  1. Apparently, the post body is empty. So, the implementation of the API must be wrong.
  2. Ctrl + F sendSignedRequest:

    ChromeExOAuth.prototype.sendSignedRequest = function(url, callback, opt_params) {
      var method = opt_params && opt_params['method'] || 'GET';
      var body = opt_params && opt_params['body'] || null;
      var params = opt_params && opt_params['parameters'] || {};
      var headers = opt_params && opt_params['headers'] || {};
    var signedUrl = this.signURL(url, method, params);
    // Hmm...? Where is `params` being passed...? ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) { if (xhr.readyState == 4) { callback(xhr.responseText, xhr); } }); };
  3. signURL doesn't modify params, so that's not a problem.
  4. Ctrl + F sendRequest:
    ChromeExOAuth.sendRequest = function(method, url, headers, body, callback) {
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function(data) {
        callback(xhr, data);
      }
      xhr.open(method, url, true);
      if (headers) { . . . }
      xhr.send(body); // <-- !!!
    };
  5. Got it! body has to be used instead of parameters.
  6. Backtracks the body variable to the request['body'] (see 2).
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Great that you took the time to jot down how you arrived at the conclusion. – Jon Nylander May 13 '12 at 19:49
  • Great detailed response. Thank you. However, changing from 'parameters' to 'body' didn't seem to work either. I'm still getting the same error response. – Sparragus May 17 '12 at 00:36
  • @Sparragus Have you already tried adding the `Content-Length` header? The value has to be equal to the size of the body. – Rob W May 17 '12 at 10:11
  • I just added `Content-Length` and started getting a different error: `{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}` I'm allowing my application on Tumblr (using the oauth procedure). I will double check my keys and debug why this is happening. – Sparragus May 17 '12 at 22:45
  • @RobW I just noticed this error: `Refused to set unsafe header "Content-Length"` [The reason](http://stackoverflow.com/questions/2623963/webkit-refused-to-set-unsafe-header-content-length) seems to be security. – Sparragus May 17 '12 at 22:58