AWS Lambda w/ Google Vision API throwing PEM_read_bio:no start line or Errno::ENAMETOOLONG
AWS Lambda w/ Google Vision API throwing PEM_read_bio:no start line or Errno::ENAMETOOLONG
目标:用户上传到S3,触发Lambda获取文件并发送到GoogleVisionAPI进行分析,return查看结果。
根据 this,google-cloud
需要本机库并且必须针对 lambda 是 运行ning 的 OS 进行编译。使用 lambda-packager
引发错误,但一些互联网搜索发现使用带有 Node 和 NPM 的 EC2 改为 运行 安装。本着解决这个问题的精神,这就是我为让它大部分工作而做的*。至少 lambda 不再给我 ELF header 错误。
我目前的问题是,有两种调用 Vision 的方法 API,都不起作用,而且 return 都是不同的错误(大部分)。
常用代码:这段代码总是一样的,它在函数的顶部,我把它分开是为了让后面的代码块专注于这个问题.
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'my-awesome-bucket';
const gCloudConfig = {
projectId: 'myCoolApp',
credentials: {
client_email: 'your.serviceapi@project.email.com',
private_key: 'yourServiceApiPrivateKey'
}
}
const gCloud = require('google-cloud')(gCloudConfig);
const gVision = gCloud.vision();
使用detect()
:此代码总是return错误Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
。理论上它应该有效,因为 URL 是 public。通过搜索错误,我认为这可能是一个 HTTPS 问题,所以我什至尝试了一个变体,我用 HTTP 替换了 HTTPS,但得到了同样的错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
const img = S3.getSignedUrl('getObject', params);
gVision.detect(img, ['labels','text'], function(err, image){
if(err){
console.log('vision error', err);
}
console.log('vision result:', JSON.stringify(image, true, 2));
});
}
Using detectLabels()
: 此代码总是 returns Error: ENAMETOOLONG: name too long, open ....[the image in base64]...
。根据建议,认为该方法不应传递 base64 图像,而应传递 public 路径;这可以解释为什么它说名称太长(base64 图像相当 URL)。不幸的是,这给出了上面的 PEM 错误。我也尝试过不进行 base64 编码并直接从 aws 传递 object 缓冲区,但这也导致了 PEM 错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
S3.getObject(params, function(err, data){
const img = data.Body.toString('base64');
gVision.detectLabels(img, function(err, labels){
if(err){
console.log('vision error', err);
}
console.log('vision result:', labels);
});
});
}
根据Best Practices,图片应该是base64编码的。
从 API 文档和示例以及其他任何内容来看,我似乎正确地使用了它们。我觉得我已经阅读所有这些文档一百万遍了。
如果 NAMETOOLONG 错误需要 base64 内容,我不确定该怎么做。这些图片不超过 1MB。
*PEM 错误似乎与凭据有关,因为我了解所有这些凭据的工作原理以及模块是如何在 EC2(没有任何类型的 PEM 文件)上编译的,这可能成为我的问题。也许我需要在 运行ning npm install
之前设置一些凭据,就像需要在 linux 盒子上安装一样?这开始超出我的理解范围,所以我希望这里有人知道。
理想情况下,使用 detect
会更好,因为我可以指定我想要检测的内容,但只要从 Google 获得任何有效响应就很棒了。非常感谢你们能提供的任何线索。
因此,与另一位同事的谈话让我考虑放弃 API 的整个加载并使用 google-cloud
模块。相反,我应该考虑通过 curl
尝试 Cloud REST API,看看它是否可以那样工作。
长话短说,发出 HTTP 请求并使用 Google 云的 REST API 是我解决这个问题的方法。
这是我现在可以使用的 lambda 函数。可能仍然需要调整,但这是有效的。
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'yourBucket';
const fs = require('fs');
const https = require('https');
const APIKey = 'AIza...your.api.key...kIVc';
const options = {
method: 'POST',
host: `vision.googleapis.com`,
path: `/v1/images:annotate?key=${APIKey}`,
headers: {
'Content-Type': 'application/json'
}
}
exports.handler = (event, context, callback) => {
const req = https.request(options, res => {
const body = [];
res.setEncoding('utf8');
res.on('data', chunk => {
body.push(chunk);
});
res.on('end', () => {
console.log('results', body.join(''));
callback(null, body.join(''));
});
});
req.on('error', err => {
console.log('problem with request:', err.message);
});
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
S3.getObject(params, function(err, data){
const payload = {
"requests": [{
"image": {
"content": data.Body.toString('base64')
},
"features": [{
"type": "LABEL_DETECTION",
"maxResults": 10
},{
"type": "TEXT_DETECTION",
"maxResults": 10
}]
}]
};
req.write(JSON.stringify(payload));
req.end();
});
}
目标:用户上传到S3,触发Lambda获取文件并发送到GoogleVisionAPI进行分析,return查看结果。
根据 this,google-cloud
需要本机库并且必须针对 lambda 是 运行ning 的 OS 进行编译。使用 lambda-packager
引发错误,但一些互联网搜索发现使用带有 Node 和 NPM 的 EC2 改为 运行 安装。本着解决这个问题的精神,这就是我为让它大部分工作而做的*。至少 lambda 不再给我 ELF header 错误。
我目前的问题是,有两种调用 Vision 的方法 API,都不起作用,而且 return 都是不同的错误(大部分)。
常用代码:这段代码总是一样的,它在函数的顶部,我把它分开是为了让后面的代码块专注于这个问题.
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'my-awesome-bucket';
const gCloudConfig = {
projectId: 'myCoolApp',
credentials: {
client_email: 'your.serviceapi@project.email.com',
private_key: 'yourServiceApiPrivateKey'
}
}
const gCloud = require('google-cloud')(gCloudConfig);
const gVision = gCloud.vision();
使用detect()
:此代码总是return错误Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
。理论上它应该有效,因为 URL 是 public。通过搜索错误,我认为这可能是一个 HTTPS 问题,所以我什至尝试了一个变体,我用 HTTP 替换了 HTTPS,但得到了同样的错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
const img = S3.getSignedUrl('getObject', params);
gVision.detect(img, ['labels','text'], function(err, image){
if(err){
console.log('vision error', err);
}
console.log('vision result:', JSON.stringify(image, true, 2));
});
}
Using detectLabels()
: 此代码总是 returns Error: ENAMETOOLONG: name too long, open ....[the image in base64]...
。根据建议,认为该方法不应传递 base64 图像,而应传递 public 路径;这可以解释为什么它说名称太长(base64 图像相当 URL)。不幸的是,这给出了上面的 PEM 错误。我也尝试过不进行 base64 编码并直接从 aws 传递 object 缓冲区,但这也导致了 PEM 错误。
exports.handler = (event, context, callback) => {
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
S3.getObject(params, function(err, data){
const img = data.Body.toString('base64');
gVision.detectLabels(img, function(err, labels){
if(err){
console.log('vision error', err);
}
console.log('vision result:', labels);
});
});
}
根据Best Practices,图片应该是base64编码的。
从 API 文档和示例以及其他任何内容来看,我似乎正确地使用了它们。我觉得我已经阅读所有这些文档一百万遍了。
如果 NAMETOOLONG 错误需要 base64 内容,我不确定该怎么做。这些图片不超过 1MB。
*PEM 错误似乎与凭据有关,因为我了解所有这些凭据的工作原理以及模块是如何在 EC2(没有任何类型的 PEM 文件)上编译的,这可能成为我的问题。也许我需要在 运行ning npm install
之前设置一些凭据,就像需要在 linux 盒子上安装一样?这开始超出我的理解范围,所以我希望这里有人知道。
理想情况下,使用 detect
会更好,因为我可以指定我想要检测的内容,但只要从 Google 获得任何有效响应就很棒了。非常感谢你们能提供的任何线索。
因此,与另一位同事的谈话让我考虑放弃 API 的整个加载并使用 google-cloud
模块。相反,我应该考虑通过 curl
尝试 Cloud REST API,看看它是否可以那样工作。
长话短说,发出 HTTP 请求并使用 Google 云的 REST API 是我解决这个问题的方法。
这是我现在可以使用的 lambda 函数。可能仍然需要调整,但这是有效的。
'use strict';
const AWS = require('aws-sdk');
const S3 = new AWS.S3();
const Bucket = 'yourBucket';
const fs = require('fs');
const https = require('https');
const APIKey = 'AIza...your.api.key...kIVc';
const options = {
method: 'POST',
host: `vision.googleapis.com`,
path: `/v1/images:annotate?key=${APIKey}`,
headers: {
'Content-Type': 'application/json'
}
}
exports.handler = (event, context, callback) => {
const req = https.request(options, res => {
const body = [];
res.setEncoding('utf8');
res.on('data', chunk => {
body.push(chunk);
});
res.on('end', () => {
console.log('results', body.join(''));
callback(null, body.join(''));
});
});
req.on('error', err => {
console.log('problem with request:', err.message);
});
const params = {
Bucket,
Key: event.Records[0].s3.object.key
}
S3.getObject(params, function(err, data){
const payload = {
"requests": [{
"image": {
"content": data.Body.toString('base64')
},
"features": [{
"type": "LABEL_DETECTION",
"maxResults": 10
},{
"type": "TEXT_DETECTION",
"maxResults": 10
}]
}]
};
req.write(JSON.stringify(payload));
req.end();
});
}