Reactでaxiosを使用してAPI Gateway連携済みのLambda(Python)からOpenWeatherMap APIをFetchする

## 概要
タイトル長いですが、タイトル通りのこと実現するための手順を記載します。
それぞれの技術の深掘りはしません。
これを経ることで、最終的に東京の天気を開発者ツールのコンソールログで出力させることができます。

## 目次
- 全体の構成
- OpenWeatherMapでAPIキーを発行する
- AWS Lambda(Python)でOpenWeatherMap APIをたたく
- Amazon API GatewayにLambdaを連携させてAPIをデプロイする
- ReactでAPI通信を可能にするライブラリ(axios)を使ってデプロイしたAPIをたたく(現在の東京の天気を出力)

## 全体の構成
システムの全体構成は以下のようになっています。
※この構成を組んで何度かAPIを叩くくらいならAWSのコストは発生しない想定です
![lambda_api.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/15968fa8-b376-8c59-36bf-a5294a846160.png)

## OpenWeatherMapでAPIキーを発行する
以下のURLからOpenWeatherMapに登録する。（無料プランでok）
https://openweathermap.org/
登録後、ヘッダー部分右側にあるユーザ名をクリックし、My API Keysで発行したAPI Keyをコピーしてメモっておいてください。

本サービスへの登録は、以下の記事などを参考にしてください。手軽かつ無料でできます。
https://auto-worker.com/blog/?p=1612

## AWS Lambda(Python)でOpenWeatherMap APIをたたく
AWSのアカウントは持っている前提です。
### Lambda functionの作成

マネージメントコンソールの検索欄にlambdaと入力しLambdaを開きます。
関数の作成を押下し、名前を決めて、Pythonを選択します。
![02.Lambda作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/77f7f3b1-90f2-670b-e96c-e52803ffe6bf.png)
以下の表示が出たら作成成功です。
![03.ver3_lmabda.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/8b191183-159b-6d1a-6c9a-065c8cc8051b.png)


以下のコードをコードを記述する欄に書き込みます。
![04.Lambda_Code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/8e819b62-a00f-a368-1be0-f7aac500d6af.png)
コピペ用にコードを置いておきます。
```python:lambda_function.py
import requests
import os
import json

CITY_NAME = os.environ['CITY_NAME']
API_KEY = os.environ['API_KEY']

def get_wether(event):
    api = "http://api.openweathermap.org/data/2.5/weather?units=metric&q={}&APPID={}".format(CITY_NAME,API_KEY)
    url = api.format(city = CITY_NAME, key = API_KEY)
    response = requests.get(url)
    data = response.json()
    jsonText = json.dumps(data, indent=4)
    print(jsonText)
    return jsonText

def lambda_handler(event, context):
    # TODO implement
    result = get_wether(event)
    dic = json.loads(result) 
    return dic
     
```
次に、環境変数を設定します。CITY_NAMEとAPI_KEYを設定します。先程のOpenWeatherMapのAPI Keyを使います。また、天気を取得する地域は、tokyoにします。
![07.環境変数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/dbcd09e6-004a-19e8-57cb-8edabb4b9390.png)

### LambdaにLayerを追加
requestモジュールをimportするためにLayerを設定します。
以下はLayerの設定後に表示される画面です。設定方法は以下のURLを参考にしてください。
https://sebenkyo.com/2021/05/21/post-1979/
![05.Layer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/d6d9163d-cb3a-ef6d-e7b6-9274b61846b0.png)


### Lambdaのテストを実行
コードの記入とLayerの設定が完了したらDeployを押下。Deployが完了したらTestを押下してLambda関数のテストを実行してください。
実行結果は以下になります。実行時の東京の天気は曇りのようです。
![06.Clouds.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/979bfaa4-888a-46c6-8027-733fffa233ed.png)

ここまでで、AWS Lambdaを使って外部APIをたたくことができました。

## Amazon API GatewayにLambdaを連携させてAPIをデプロイする
次に、作成したLambdaをAPI Gatewayに連携させます。
### Lambdaを登録してAPIをデプロイ
API Gatewayに移動し、APIを作成を押下します。
![08.APIを作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/43005c9c-1ba5-7dc9-c9ab-f97edf3ec8b0.png)

APIタイプは、RESTを選択し、新しいAPIにチェックをつけ、APIの名前(任意のものでok)を入力します。
![09.作成完了.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/4333f0a0-b344-5068-0f49-56bad7b6a28d.png)

APIが作成できました。

API Gatewayのエンドポイントの設定を行います。
アクションからメソッドの作成を選択します。
![10.メソッドの作成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/d5d22943-c644-e589-2605-3cfd280d2ffc.png)

メソッドの設定をします。
Getを選択してチェックマークを押下、その後以下の設定を行い、名前には作成したLambda関数名を入力して保存します。
![11.メソッドの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/ca5f127b-7b1e-8512-80ee-8c0fac4473d3.png)

![12.APIgateway完成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/43ff29f0-dcb8-1346-74ec-7034a8e1c046.png)

これで、GETメソッドが作成できました。
作成したlambda関数を呼び出せるようになりました。

### テストを実行
GETメソッドを選択した状態で、以下の縦長のテストを選択し、
![13.テスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/ee2258bb-f946-3e8b-3517-987872badf23.png)

さらに、テストを押下します。
![14.テスト押下.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/4260512d-955f-50cb-9ba7-40320615d6bb.png)
結果が出力されました。
![15.テスト結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/3447e868-47b6-aa0e-95a9-bc5e5db81703.png)

### CROSを有効化
続いて、例えばReactからAPIを叩く際には、CROSと呼ばれるセキュリティ機能の制限をくぐり抜ける必要があります。CROSの説明は以下です。

> Cross-origin resource sharing (CORS) は、ブラウザで実行されているスクリプトから開始されるクロスオリジン HTTP リクエストを制限するブラウザのセキュリティ機能です。REST API のリソースが非シンプルクロスオリジンの HTTP リクエストを受け取る場合、CORS サポートを有効にする必要があります。

そんなわけで、API GatewayでCROSの有効化を実施します。
メソッドの設定と同様に、GETを選択して、アクションからCROSの有効化を選択します。
![16.cros設定①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/1a60e34c-d749-1ce1-d2e9-3cabfbbc26ad.png)
以下のように設定して、既存のCROSヘッダーを置換を押下します。
![17.cros設定②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/d27b170e-e210-9cf0-b116-582edd09c73f.png)

### APIのデプロイ
最後にAPIのデプロイを行います。メソッドの作成と同様に、GETを選択して、アクションからAPIのデプロイを押下し、新しいステージを選んで、任意のステージ名をつけてデプロイを完了させます。
![18.apiデプロイ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/696d299e-124b-7d33-6cd7-12164af6f9fa.png)
デプロイが完了するとURLが払い出されますので、押下してAPIが実行されれば成功です。
![19.url払い出し.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/8e6affa3-5545-eb2c-bd6e-541574f9737a.png)
urlをクリックすると以下のようにAPIがcallされます。
![20.api結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/4ca3daa9-ddb0-94ea-2b60-25ddc41b0f25.png)

ここまでで、API GatewayとLambdaの連携が完了しました。

## ReactでAPI通信を可能にするライブラリ(axios)を使ってデプロイしたAPIをたたく(現在の東京の天気を出力)
最後に、ローカルのReactで書いたスクリプトからAPIをcallします。
### Reactプロジェクトを作成しサーバを起動
以下でReactの用意をします。チュートリアルを見ると良いです。
https://ja.reactjs.org/docs/create-a-new-react-app.html
ターミナルを起動して、好ききなディレクトリに移動し、以下のコマンドを実行します。
```terminal:reactの導入
#今いるディレクトリにReactプロジェクトをcreateする。
> npx create-react-app my-app

#Reactのプロジェクトに移動
> cd my-app

#サーバを起動
> npm start
```
ブラウザで以下の画面が開かれればreactの導入及び、サーバの起動が成功です。
![21.react.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/97eafe1e-2817-f1e5-342f-4d2ea9465ed6.png)

### axiosを使ったAPI通信
次にReactで手軽にAPI通信処理を実装できるaxiosというライブラリをつかえるようにするため、my-appディレクトリでterminalから以下のコマンドを実行します。
```terminal:my-app
> npm install axios
```
次に、以下のコマンドでvscodeを開きます。
```terminal:my-app
> code .
```
my-appディレクトリをvscodeで開けたら、src/App.jsを選択し、スクリプトを以下のコードに置換します。そのままコピペで使えますが、get('URL')の部分には、自分で作成したAPIのURLを入れてください。
```react:App.js
import logo from './logo.svg';
import './App.css';
import axios from "axios";


function App() {    
  axios
  .get('URL')
  .then((response) => {
      console.log(response);
  })
  .catch((error) => {
      console.log(error);
  });


  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

```
ファイルを保存をして、起動しているサーバがsuccessfullyとなれば成功しているはずですので、先程サーバを起動した時に開いたブラウザ(chrome)を開き、開発者ツールのコンソールログを確認します。APIが出力できていることを確認できれば終了です。

![22.react結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/754596/c6803522-fead-176b-192c-d6d903e5bc0b.png)


## おわりに
今回はReactとAWSを使って手軽に外部APIをフェッチする方法を紹介しました。
今後はAmplifyやDynamoDBなどと連携することを考えています。
それでは。