【问题标题】:Google Drive API push notifications can't be stopped / cancelledGoogle Drive API 推送通知无法停止/取消
【发布时间】:2013-07-21 21:44:06
【问题描述】:

我正在观看云端硬盘资源。设置手表(使用带有 node.js 和 drive.file.watch 的 googleapis 0.2.13-alpha 客户端):

exports.subscribeDriveCallbacksCmd = function( user, fileId ){
  var userId = user.id;
  var baseUrl = exports.BASE_URL;
  var subscribeUrl = baseUrl+"/incoming/file";
  var watchId = 'id-'+fileId+'-'+(new Date()).getTime();
  var subscription = {
    id: watchId,
    token: userId+':'+fileId,
    type: 'web_hook',
    address: subscribeUrl,
    params:{
      ttl: 600
    }
  };
  var params = {
    fileId: fileId
  };

//var cmd = client.drive.files.watch(参数,订阅);

// FIXME - 破解 RPC 实现中的错误 var hack = {频道:订阅}; for(参数中的var键){ hack[key] = 参数[key]; } var cmd = client.drive.files.watch(hack);

返回命令; };

var cmd = exports.subscribeDriveCallbacksCmd(user, '0ZZuoVaqdWGhpUk9PZZ' ); var batch = client.newBatchRequest(); 批处理.add(cmd); batch.withAuthClient(user.auth).execute(cb);

在此之后,我收到了以下回复

{ kind: 'api#channel',
    id: 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592',
    resourceId: 'WT6g4bx-4or2kPWsL53z7YxZZZZ',
    resourceUri: '@987654321@',
    token: '101852559274654726533:0ZZuoVaqdWGhpUk9PZZ',
    expiration: '1374537347934' }
以及带有以下标头的同步回调
  'x-goog-channel-id': 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592',
  'x-goog-channel-expiration': 'Mon, 22 Jul 2013 23:55:47 GMT',
  'x-goog-resource-state': 'sync',
  'x-goog-message-number': '1',
  'x-goog-resource-id': 'WT6g4bx-4or2kPWsL53z7YxZZZZ',
  'x-goog-resource-uri': '@987654322@',
  'x-goog-channel-token': '101852559274654726533:0ZZuoVaqdWGhpUk9PZZ',
  'user-agent': 'APIs-Google; (+@987654323@)

然而,这有几个问题:

  • 这两个返回的resource-id与我订阅手表时传递的fileId不匹配。它确实与 resource-uri 中给出的 ID 匹配
  • 尝试使用此处返回的 resourceID 或订阅时传递的 fileId,在尝试停止频道时会返回错误。

为 drive.channel.stop 给出的错误取决于我如何调用。如果我使用 Channel: Stop 页面底部的 API Explorer,为 resourceId 参数提供 resourceId 或 fileId,我会得到


404 Not Found

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "notFound",
    "message": "Channel not found"
   }
  ],
  "code": 404,
  "message": "Channel not found"
 }
}

如果我在这段代码中使用 node.js 库:

exports.cancelDriveCallbacksCmd = function( watchId, fileId, resourceId ){
  var body = {
    id: watchId,
    resourceId: resourceId
  };
  var cmd = client.drive.channels.stop( body );
  return cmd;
};
var cmd = exports.cancelDriveCallbacksCmd( 'id-0ZZuoVaqdWGhpUk9PZZ-1374536746592', '0ZZuoVaqdWGhpUk9PZZ', 'WT6g4bx-4or2kPWsL53z7YxZZZZ' );
var batch = client.newBatchRequest();
batch.add(cmd);
batch.withAuthClient(user.auth).execute(cb);

我得到了错误

{ code: 500,
  message: 'Internal Error',
  data: 
   [ { domain: 'global',
       reason: 'internalError',
       message: 'Internal Error' } ] }
我怀疑这与 Bug 59 有关,它有一个解决方法(这是我在上面使用的 hack 代码)但应该在本周的某个时候修复,我理解。

所以我把它改成了这段代码,它解决了 files.watch 的错误:


exports.cancelDriveCallbacksCmd = function( watchId, fileId, resourceId ){
  var params = {};
  var body = {
    id: watchId,
    resourceId: resourceId,
    fileId: fileId
  };

  //var cmd = client.drive.channels.stop( params, body );

  // FIXME - hack around bug in RPC implementation
  var hack = {channel:body};
  for( var key in params ){
    hack[key] = params[key];
  }
  var cmd = client.drive.channels.stop( hack );
  console.log( 'cancelDriveCallbacksCmd', hack );

  return cmd;
};

但我得到同样的 500 错误。

关于我可能做错了什么或者如何去调试我可能出错的地方有什么想法吗?

【问题讨论】:

  • 第一个问题的答案:resourceId与fileId无关,仅使用1.从Google返回的resourceId和2.您提供的频道ID退订。
  • 仅供参考,频道资源已绑定到用户。如果你创建了关于用户 A 资源的频道,你应该取消订阅用户 A 的凭据,否则你会得到 404。
  • 更新了附加代码。如果resourceId与fileId无关,为什么resourceUrl包含fileId作为它的一部分?为什么确认返回时没有说明他们正在观看什么文件?但是我传递了通道 ID(我分配的)和资源 ID(它返回的)并且得到了有问题的错误。这两个操作都是由同一个用户完成的,尽管是通过两个不同的应用程序生成的两个不同的 access_tokens。

标签: google-drive-api google-api-nodejs-client


【解决方案1】:
  1. 推送通知旨在监视任何 api 资源,尽管它目前仅支持更改和文件。因此,它需要所有资源类型的唯一 resourceId。这就是他们的 resourceId 不等于 fileId 的原因。

  2. 确认会返回有关它正在观看的文件的信息。检查您的回复的标题。此外,您可以根据需要使用令牌来保存频道特定信息。

  3. 如果您使用 API Explorer,则无法取消订阅频道,因为如您所知,推送通知需要通过 apis 控制台对 url 进行额外验证,并且 apis explorer 未经过身份验证才能访问您的通知。出于安全原因,它按预期工作。我会报告这个问题,以免人们对此感到困惑。

  4. fileId 不会进入请求正文。它应该是参数之一。此外,您应该向Channels.stop() 提出退订请求。像这样:

订阅代码:

var channel= {
  'id': 'yourchannelid',
  'type': 'web_hook',
  'address': 'https://notification.endpoint'
};
var request = client.drive.files.watch({'fileId': fileId, 'channel':channel});

退订代码

var request = client.drive.channels.stop({'id': channelId, 'resourceId':resourceId});

【讨论】:

  • Re: item 2) 如上所示,我使用了令牌,因为似乎没有任何标题与正在监视的文件 ID 一起返回,而我没有'认为从长远来看,解析 resource-uri 标头是可靠的。
  • Re: item 4) 你发现了代码的问题之一!我错误地剪切/粘贴了 Bug 59 hack-around 并且调用了 files.watch 而不是 channels.stop。我更新了上面的问题,以反映我尝试调用 channels.stop 的两种方式,两者都产生 500 错误。
  • Re: 项目 1 和 3) 感谢您澄清这些要点!两者都有意义,尽管由于我经常使用 API Explorer 根据我的代码进行测试,它确实使事情变得混乱。感谢您的解释和帮助。
  • 4) 您尝​​试过我发布的代码吗?该错误是一个已知问题,我发布的代码是经过测试的解决方法。
  • 这似乎是一个错误。很快就会修复。
猜你喜欢
  • 1970-01-01
  • 2017-05-31
  • 2017-05-13
  • 1970-01-01
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多