LoginSignup
3
3

More than 1 year has passed since last update.

【初心者向け】Vue+API Gateway+LambdaでサーバレスWebアプリを作った際に遭遇した問題

Last updated at Posted at 2020-08-11

概要

「AWSを使って、サーバレスアプリを作りたい!」と思い実践したのですが、Lambda関連で結構な壁があったので備忘がてら残します。

ハマりポイントは以下3つ。

  • LambdaのResponseは特定のJSON形式でないとNGな話
  • API連携の際に、CROS Policyでエラーになった話
  • APIに認証を噛ませる際は、accessTokenではなくidTokenを使用する話

LambdaのResponseは特定のJSON形式でないとNGな話

今回はフロントサイドはvueで作成、そこからAPIGatewayを通してLambdaのFunctionを呼び出すという構成でした。
このFunctionの返却の仕方は何でもよい訳ではなくJSONの形式が決まっています。

参考:https://aws.amazon.com/jp/premiumsupport/knowledge-center/malformed-502-api-gateway/

以下は、Lambdaを通してTwitterに投稿する関数の例です


exports.handler = (event, context, callback) => {
    let date = new Date();
    twitter_client.post('statuses/update', {status: 'テスト投稿。from lambda ' + date},  function(error, tweet, response){
        if(error) {
            //エラーハンドリング
        }
        callback(null, JSON.stringify(response));
    });
};

関数単体はテスト時に動いても、上記のような正しい形式でないと、実際のフロントからの実行時には500エラーを返すので注意。

API連携の際に、CROS Policyでエラーになった話 

「JSONを返す必要があるということはわかったぜ!これでオッケーや!」と思ったら、まだ駄目でした。
今度はフロント側でエラーになりました。。。ブラウザのF12コンソールでエラーの内容を確認すると
「Access to XMLHttpRequest at 'http:/~' from origin 'http://localhost:8080' has been blocked by CORS policy:
…」と書いてありました。
あぁーCROSね、なんかAPIGatewayで設定があった気がするなーと思いいろいろググります。

※CROSについては以下の記事が参考になりました。
https://qiita.com/att55/items/2154a8aad8bf1409db2b

結論から言うと、以下のように設定するのが正解でした。
レスポンスのヘッダーに
Access-Control-Allow-Headers (使用するHeadersの値を追加)
Access-Control-Allow-Origin (許可するリソースを追加)
Access-Control-Allow-Credentials (これはなくてもいいかも)
Access-Control-Allow-Methods (必要なメソッドを追加)
を追加します。
image.png

lambdaの関数のレスポンスに直接書いているやり方もありましたが、
調べて実際に動かしたところこれでも大丈夫。(ケースバイケースだが多分ほとんどの場合これがベターな気がする)

APIに認証を噛ませる際は、accessTokenではなくidTokenを使用する話

これはハマったというほどではなかったが、少し勘違いがあったので記載。
上記の問題でAPI通信は問題なく通るようになったが、APIには認証をかけたほうがよい。

認証のかけ方もいくつか方法があるが、今回はcognitoユーザプールを使った。
※cognitoを使ったログイン機能を実装していることが前提です。

手順としては
1.APIgatewayのコンソールからAuthorizersを作成
2.使用するAPIに適用する
の2 STEEP(めちゃ簡単)
image.png

フロントのコードは以下のような感じで実装

App.vue
import { Auth } from 'aws-amplify'
import axios from 'axios'

let cognitoUser = await Auth.currentAuthenticatedUser()
this.signedIn = true
this.username = cognitoUser.username
let token = cognitoUser.signInUserSession.idToken.jwtToken;
console.log(cognitoUser.signInUserSession);

中略
APIfunction(){
        axios
          .get('APIのURL',
            {
              headers: {
                Authorization: token
              }
            }
          )
          .then(function (response) {
            // handle success
            console.log(response);
            alert("success");
            alert(response);
          })
          .catch(function (error) {
            // handle error
            console.log(error);
            alert("error");
            alert(error);
          })
    }

signInUserSessionの中にはaccessTokenという似たプロパティもあるが、こっちではなくidTokenを使用した点に注意。
※accessTokenでも認証機能を作ることはできるかも知れませんが、詳細は調査しきれず…(だれか知っている人がいたら教えてください…)

まとめ

AWSを使いこなすまでの道のりは遠い…
一方で使いこなすと非常に便利だということも実感できた。前進あるのみ。

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3