0

更新

我能够获得我的原始代码,并且这些建议在单独运行时也能正常工作。但是,我需要做的是从 FirebaseonRequestonCall函数中调用它。当此代码被这些包裹时,格式错误的标头和授权请求仍然是一个问题。我们以这种方式使用许多其他 API,因此令人费解的是 Clarifaiai API 为何会出现这些问题。关于将它与 Firebase 一起使用的任何建议?

原来的

Clarifai 的新手,在尝试从 Food Model 检索模型输出时遇到一些身份验证问题。

我尝试了两种不同的键:

  • 从我在门户中创建的应用程序生成的 API 密钥
  • API 密钥 - 我为自己生成的个人访问令牌

在这两种情况下,我都会遇到Empty or malformed authorization header回应。

{
   "status":{
      "code":11102,
      "description":"Invalid request",
      "details":"Empty or malformed authorization header. Please provide an API key or session token.",
      "req_id":"xyzreasdfasdfasdfasdfasf"
   },
   "outputs":[
      
   ]
}

我已按照以下文章拼凑此代码。这是在 Node 10 环境中运行的。

  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization", "Key xyzKey");

  return new Promise((resolve, reject) => {
    stub.PostModelOutputs(
      {
        model_id: 'bd367be194cf45149e75f01d59f77ba7',
        inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }],
      },
      metadata,
      (err, response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }

        resolve(JSON.stringify(response));
      }
    );
  });
}
4

3 回答 3

2

更新:在 7.0.2 之前的版本中存在一个问题,如果您有另一个使用@grpc/grpc-js不同版本的库,则该grpc.Metadata对象不一定是从clarifai-grpc-nodejs正在使用的库版本构造的。

要解决此问题,请更新clarifai-grpc-nodejs库,并需要这样的grpc对象:

const {ClarifaiStub, grpc} = require("clarifai-nodejs-grpc");

以前,grpc对象是直接从 导入的@grpc/grpc-js,这是问题的根源。


有两种向 Clarifai API 进行身份验证的方法:

  • 使用特定于应用程序的 API 密钥,这意味着 API 密钥附加到应用程序并且只能在该应用程序内部执行操作,
  • 使用特定于用户的个人访问令牌 (PAT),这意味着您可以对用户拥有/有权访问的所有应用程序进行评估/操作/执行操作(还可以自己创建/更新/删除应用程序)。

使用 PAT 时,您必须在请求数据中指定您的目标应用程序。使用 API 密钥,这不是必需的。

我已经使用有效的 API 密钥测试了您的示例(使用 Node 12,尽管它也应该在 10 中工作)并且它可以正常工作(在将其放入异步函数之后)。这是一个完整的可运行示例(替换YOUR_API_KEY为您的有效 API 密钥)。

function predict() {
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization", "Key YOUR_API_KEY");

  return new Promise((resolve, reject) => {
    stub.PostModelOutputs(
      {   
        model_id: 'bd367be194cf45149e75f01d59f77ba7',
        inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }], 
      },  
      metadata,
      (err, response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }

        resolve(JSON.stringify(response));
      }   
    );  
  }); 
}

async function main() {
    const response = await predict();
    console.log(response);
}

main();

如果您想在上面的示例中使用 PAT,则必须更改两件事。首先,将 API 密钥替换为 PAT:

...
metadata.set("authorization", "Key YOUR_PAT");
...

向方法请求对象添加应用程序 ID。

...
    stub.PostModelOutputs(
      {
         user_app_id: {
           user_id: "me",  // The literal "me" resolves to your user ID.
           app_id: "YOUR_APPLICATION_ID"
         },
        model_id: 'bd367be194cf45149e75f01d59f77ba7',
        inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }], 
      },
...
于 2020-10-29T17:49:11.380 回答
0

确保您尊重在代码中传递密钥的格式,如下所示:

const metadata = new grpc.Metadata();
metadata.set("authorization", "Key {YOUR_CLARIFAI_API_KEY}");

确保“密钥”存在。

让我知道。

于 2020-10-29T10:17:36.027 回答
0

编辑:所以看起来 Firebase 不支持自定义标头。这可能会影响“授权”标头。至少这是我最好的猜测。请参阅以下票证中的评论。

Firebase 托管自定义标头不起作用


以下代码适用于我:

{
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization", "Key {APP API KEY}");

  return new Promise((resolve, reject) => {
    stub.PostModelOutputs(
      {
        model_id: 'bd367be194cf45149e75f01d59f77ba7',
        inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }],
      },
      metadata,
      (err, response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }
        console.log(JSON.stringify(response));
        resolve(JSON.stringify(response));
      }
    );
  });
}

{虽然我不确定这是否反映在您正在运行的实际代码中,但有一个缺失。在这种情况下,我使用的是 APP API 密钥(当您创建应用程序时,应用程序详细信息页面上会有一个 API 密钥。

听起来您可能正在使用个人访问令牌,可以这样使用:

{  
  const { ClarifaiStub } = require('clarifai-nodejs-grpc');
  const grpc = require('@grpc/grpc-js');
  const stub = ClarifaiStub.json();
  const metadata = new grpc.Metadata();
  metadata.set("authorization", "Key {Personal Access Token}"); // Sounds like you've made the personal access token correctly - go into settings, then authentication, then create one.  Make sure it has proper permissions (I believe all by default).

  return new Promise((resolve, reject) => {
    stub.PostModelOutputs(
      {
        user_app_id: {
          user_id: "{USER ID}",  // I used my actual ID, I did not put 'me'.  You can find this under your profile.
          app_id: "{APP NAME}" // This is the app ID found in the upper left corner of the app after it is created - not the API Key.  This is generally what you named the app when you created it.
        },
        model_id: 'bd367be194cf45149e75f01d59f77ba7',
        inputs: [{ data: { image: { url: 'https://samples.clarifai.com/metro-north.jpg' } } }],
      },
      metadata,
      (err, response) => {
        if (err) {
          return reject(`ERROR: ${err}`);
        }
        console.log(JSON.stringify(response));
        resolve(JSON.stringify(response));
      }
    );
  });
}

请务必填写:{Personal Access Token}、{USER ID} 和 {APP NAME}。我使用了我的实际用户 ID(在配置文件中找到),并且应用名称不是应用的 API 密钥,而是在应用程序详细信息页面上时左上角的名称。这个电话对我有用。

于 2020-11-02T06:32:59.200 回答