Search code examples
javascriptpythonpostgoogle-oauth

JavaScript equivalent of Python's oauth2client POST request to Google Reminders


I would like to port this open source Python library for Google Reminders to JavaScript:

https://github.com/jonahar/google-reminders-cli

I have ported the authorization with the help of https://developers.google.com/identity/protocols/OAuth2UserAgent

My JavaScript version: https://github.com/Jinjinov/google-reminders-js

Now I need to port the Python's oauth2client POST request:

body = {
    '5': 1,  # boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
    '6': num_reminders,  # number number of reminders to retrieve
}

HEADERS = {
    'content-type': 'application/json+protobuf',
}

    response, content = self.auth_http.request(
        uri='https://reminders-pa.clients6.google.com/v1internalOP/reminders/list',
        method='POST',
        body=json.dumps(body),
        headers=HEADERS,
    )

My XMLHttpRequest POST request returns:

  • HTTP 400 - Bad Request - if I use 'application/x-www-form-urlencoded'
  • HTTP 401 - Unauthorized - if I use 'application/json'

My code (full code with authorization and access token is on GitHub):

function encodeObject(params) {
    var query = [];
    for (let key in params) {
      let val = encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
      query.push(val);
    }
    return query.join('&');
}

function list_reminders(num_reminders, access_token, callback) {

    var body = {
        '5': 1,  // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
        '6': num_reminders,  // number of reminders to retrieve
    };

    body['access_token'] = access_token;

    //body = JSON.stringify(body);
    body = encodeObject(body);

    var xhr = new XMLHttpRequest();

    xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + body);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

    //xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list');
    //xhr.setRequestHeader('Content-type', 'application/json');

    xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
            var content_dict = JSON.parse(xhr.response);

            if (!('1' in content_dict)) {
                console.log('No reminders found');
            }
            else {
                var reminders_dict_list = content_dict['1'];
                var reminders = [];

                for(var reminder_dict of reminders_dict_list) {
                    reminders.push(build_reminder(reminder_dict));
                }

                callback(reminders);
            }
        }
        else if (xhr.readyState === 4 && xhr.status === 401) {
            callback(null);
        }
    }

    //xhr.send(body);
    xhr.send(null);
}

Solution

  • I was trying to send both, the body and the access token in the same way.

    The solution is to send the access token as url encoded and the body as json:

    function list_reminders(num_reminders, access_token, callback) {
        /*
        returns a list of the last num_reminders created reminders, or
        None if an error occurred
        */
    
        var xhr = new XMLHttpRequest();
    
        xhr.open('POST', 'https://reminders-pa.clients6.google.com/v1internalOP/reminders/list' + '?' + 'access_token=' + access_token);
        xhr.setRequestHeader('Content-type', 'application/json+protobuf');
    
        xhr.onreadystatechange = function (e) {
            if (xhr.readyState === 4 && xhr.status === 200) {
                var content_dict = JSON.parse(xhr.response);
    
                if (!('1' in content_dict)) {
                    console.log('No reminders found');
                }
                else {
                    var reminders_dict_list = content_dict['1'];
                    var reminders = [];
    
                    for(var reminder_dict of reminders_dict_list) {
                        reminders.push(build_reminder(reminder_dict));
                    }
    
                    callback(reminders);
                }
            }
            else if (xhr.readyState === 4 && xhr.status === 401) {
                callback(null);
            }
        }
    
        var body = {
            '5': 1,  // boolean field: 0 or 1. 0 doesn't work ¯\_(ツ)_/¯
            '6': num_reminders,  // number of reminders to retrieve
        };
    
        xhr.send(JSON.stringify(body));
    }