AWS : Calling Rest API with IAM authentication from Node.js vs from browser javascript

huangapple go评论86阅读模式
英文:

AWS : Calling Rest API with IAM authentication from Node.js vs from browser javascript

问题

I have translated the text as requested:

"对JavaScript还很陌生,正在努力理解库等概念。

我有一个启用了IAM身份验证的AWS API Gateway,想要使用JavaScript从浏览器访问它。为了实现这一目标,我需要两个外部库,分别是:@aws-sdk/signature-v4 和 @aws-sdk/sha256-js。

现在,在我的本地Node服务器上,我可以执行"npm install"以安装所需的包,并立即使用"require"语句来使用它,就像这样:


const express = require('express');
const app = express();
const port = 3000;
const axios = require('axios');
const SignatureV4 = require('@aws-sdk/signature-v4');
const sha256 = require('@aws-crypto/sha256-js');

API_URL
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY

const apiUrl = new URL(API_URL);

const sigv4 = new SignatureV4.SignatureV4({
    service: '#Service-Name#',
    region: '#Region-Name#',
    credentials: {
        accessKeyId: AWS_ACCESS_KEY_ID,
        secretAccessKey: AWS_SECRET_ACCESS_KEY
    },
    sha256: sha256.Sha256,
});

const handler = async () => {
    const signed = await sigv4.sign({
        method: 'GET',
        hostname: apiUrl.host,
        path: apiUrl.pathname,
        protocol: apiUrl.protocol,
        headers: {
            'Content-Type': 'application/json',
            host: apiUrl.hostname, // 必填项
        },
    });

    try {
        const { data } = await axios({
            ...signed,
            url: API_URL, // 必填项
        });

        console.log('成功接收到数据:', data);
        return data;
    } catch (error) {
        console.log('发生错误', error);

        //throw error;
    }
};

app.get('/', (req, res) => {
    handler().then((result) => {
        res.send(result);
    });
});

app.listen(port, () => {
    console.log(`我正在监听 http://localhost:${port}`);
});

现在,我似乎无法在浏览器端开始。显然,"require"在浏览器JavaScript上不起作用(至少对我来说抛出了错误),因此我开始探索使用ES6导入。为此,经过一些阅读,我发现可以使用一些CDN服务器来获取所需的包,但是aws-crypto的CDN链接已损坏(https://cdn.jsdelivr.net/npm/@aws-crypto/sha256-js@4.0.0/+esm 这个链接给我带来了一个导入错误:"无法读取null的属性(读取 '__exportStar')")

所以这让我想,我在本地Node文件夹中有所需的库,我是否可以以某种方式将它们打包成ES6模块并在我的网页中使用呢?但我不知道如何做到这一点,事实上,我甚至不知道我是否在正确的方向上。所以,任何帮助将不胜感激....谢谢。"

英文:

So new to JavaScript and trying to wrap my head around libraries and all.

I have an AWS API Gateway, with IAM authentication enabled. I want to hit it from my browser using JavaScript. In order to do that, I need 2 external libraries, namely: @aws-sdk/signature-v4 and @aws-sdk/sha256-js.

Now in my local node server, I can do an "npm install" for the required packages and straight away use it using "require" statements, like this:

// JavaScript source code

const express = require('express');
const app = express();
const port = 3000;
const axios = require('axios');
const SignatureV4 = require('@aws-sdk/signature-v4');
const sha256 = require('@aws-crypto/sha256-js');



API_URL
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY


const apiUrl = new URL(API_URL);



const sigv4 = new SignatureV4.SignatureV4({
    service: '#Service-Name#',
    region: '#Region-Name#',
    credentials: {
        accessKeyId: AWS_ACCESS_KEY_ID,
        secretAccessKey: AWS_SECRET_ACCESS_KEY
    },
    sha256: sha256.Sha256,
});

const handler = async () => {
    const signed = await sigv4.sign({
        method: 'GET',
        hostname: apiUrl.host,
        path: apiUrl.pathname,
        protocol: apiUrl.protocol,
        headers: {
            'Content-Type': 'application/json',
            host: apiUrl.hostname, // compulsory
        },
    });

    try {
        const { data } = await axios({
            ...signed,
            url: API_URL, // compulsory
        });

        console.log('Successfully received data: ', data);
        return data;
    } catch (error) {
        console.log('An error occurred',error);

        //throw error;
    }
};


app.get('/', (req, res) => {
    handler().then((result) => {
        res.send(result);
    });
    
    
});

app.listen(port, () => {
    console.log(`I am listening at http://localhost:${port}`);
});

Now, I can't seem to get started on the browser side. Apparently require won't work on browser javascript (at least it threw an error for me), so I started exploring using ES6 import. For that, after some reading, I figured to use some cdn servers to get my required packages, but the cdn for aws-crypto is broken ( https://cdn.jsdelivr.net/npm/@aws-crypto/sha256-js@4.0.0/+esm this gives me an import error: "Cannot read properties of null (reading '__exportStar')
" )

So it got me thinking, I have the required libraries in my local node folder, can't I somehow package them into ES6 modules and use it in my webpage..? But I don't know how to do that, in fact, I don't even know if I am on the right track. So any help would be appreciated....Thanks.

答案1

得分: 1

Finally got it working. So mentioning in case anyone faces a similar problem.

So, after reading around I found out about "Browserify". It basically bundled the different "require" packages recursively into a single JS file, which I later embedded into my HTML page with the script tag.

Also, I used @aws-amplify/core package for signing as it was a bit easier and it worked in my browser application.

So to summarize, I did the following steps:

  1. Browserified the following script into a custom bundle:

    const amp = require('@aws-amplify/core');
    global.window.signer = amp.Signer;
    
  2. Included the custom bundle in my web app (the bundle size is 1.5MB, will have to figure out how to minimize it if possible)

  3. Now that the amplify's "signer" function was available in the global scope, I simply used it as mentioned here.

So, although I got it working this way, if anyone has a better idea, I would love to hear them out.

英文:

Finally got it working. So mentioning in case anyone faces a similar problem.

So, after reading around I found out about "Browserify". It basically bundled the different "require" packages recursively into a single JS file, which I later embeded into my html page with the script tag.

Also, I used @aws-amplify/core package for signing as it was a bit easier and it worked in my browser application.

So to summarize, I did the following steps:

  1. Browserified the following script into a custom bundle:

    const amp = require('@aws-amplify/core');
    global.window.signer = amp.Signer;
    
  2. Included the custom bundle in my web app (the bundle size is 1.5MB, will have to figure out to minimize it if possible)

  3. Now that the amplify's "signer" function was available in the global scope, I simply used it as mentiond here

So, although I got it working this way, if anyone has a better idea, I would love to hear them out.

huangapple
  • 本文由 发表于 2023年5月7日 03:44:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190797.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定