工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

APIGatewayとLambdaを一緒に使うためのメモ

背景と目的

APIGatewayとLambdaを一緒に使う場合、設定項目がたくさん用意されていて自由度は高いのだが、いろいろありすぎてどんな時に何をすればいいかわからなくなる。公式ドキュメントを読まずともある程度のことが分かるようにメモしておく。



前提

  • APIGatewayに入ってきたリクエストを、APIGateway>統合リクエスト>マッピングテンプレートを用いてJSONに成型して、Lambdaの引数eventに引き渡す


APIGateway

設定

バイナリメディアタイプ

バイナリとして受け入れるContent-Typeを設定する。たとえば、application/octet-streamやimage/jpegなど。設定しておかないと、Unsupported Media Typeというレスポンスが帰ってきてしまう。ここで設定したら、統合リクエスト>マッピングテンプレートの$input.bodyにbase64エンコードされた文字列が入るようになる。


リソース


メソッドリクエス

編集中


統合リクエス

HTTPヘッダー

  • Lambdaの引数event.params.headerに渡すデータの設定ができる。
  • クエリパラメータ、パスパラメータ、リクエストヘッダーなどいろいろなものをマッピング可能。

マッピングテンプレート

リクエストのパススルー

  • そのままだと、リクエストボディがJSONであることを期待して、jsonパースしてLambdaの引数event.body-jsonに入れる。JSONパースできない場合、Lambdaに到達する前に怒られる。
Content-Typeがtext/plainの場合

以下のようにすれば文字列を入れられる。

"body-json": "$input.body"
Content-Typeがapplication/octet-streamなどのバイナリの場合

以下のようにすれば、base64エンコードされた文字列がLambdaに渡される。もちろん、先述のバイナリメディアタイプの設定が事前にされている必要がある。

"body-json": "$input.body"

統合レスポンス

統合レスポンスは、Lambdaからのレスポンス内容に応じて、メソッドレスポンスに伝える形式を定義する部分。おそらくエラー時の整形の時に一番気を使うと思われるので、エラー処理に絞ってメモする。

Lambda エラーの正規表現

まず、PythonランタイムのLambdaで、エラーが起きた時や以下のようにわざとエラーを起こしてみると、

raise Exception("設定した文字列")

Lambdaからのレスポンスとして、統合レスポンスに以下のようなJSONが伝わる。(自前でカスタム定義することも可能だが、特に何もしなければ)

{
    "errorMessage": "設定した文字列",
    "errorType": "エラータイプ",
    "stackTrace": [
        スタックトレース,
        :
    ]
}
  • Lambda エラーの正規表現は、errorMessageの中の文字列を捕まえる条件。この条件に当てはまる場合に、メソッドレスポンスのどのステータスコードに割り当てるかも設定する。

マッピングテンプレート

Lambda エラーの正規表現で捕まえたときに、適用される。

基本形式として、Empty、Errorが定義されているので、これを少し改造することで好きなものが作れる。

  • Empty

空のJSON

#set($inputRoot = $input.path('$'))
{}
  • Errorのとき

メッセージだけ。

#set($inputRoot = $input.path('$'))
{
  "message" : "foo"
}

$inputRootは、先述のLambdaからのエラー時のレスポンスが入っているので、

{
  "message" : "$inputRoot.errorMessage"
}

などとすれば、エラーメッセージだけ取り出せる。

メソッドレスポンス

編集中


Lambda

引数event

マッピングテンプレートの生成 = リクエストのパススルーのとき

{
    "body-json": "{ボディ}",
    "params": {
        "path": {
            "pathParameter": "value",
            :
        },
        "querystring": {
            "queryParameter": "value",
            :
        },
        "header": {
            "Accept": "*/*",
            "Accept-Encoding": "gzip, deflate, br",
            "Cache-Control": "no-cache",
            "CloudFront-Forwarded-Proto": "https",
            "CloudFront-Is-Desktop-Viewer": "true",
            "CloudFront-Is-Mobile-Viewer": "false",
            "CloudFront-Is-SmartTV-Viewer": "false",
            "CloudFront-Is-Tablet-Viewer": "false",
            "CloudFront-Viewer-Country": "US",
            "Content-Type": "{Content-Type}",
            "Host": "{api-id}.execute-api.ap-northeast-1.amazonaws.com",
            "User-Agent": "PostmanRuntime/7.29.0",
            "Via": "1.1 22512dca1de1fae848b2509fed0309aa.cloudfront.net (CloudFront)",
            "X-Amz-Cf-Id": "FXfKr5sbNKhgGGfyTwehKew20UNqXsoPp7xyDL-y8TqgAkwCnWr94w==",
            "X-Amzn-Trace-Id": "Root=1-6215f7c0-12c8260b2b11d6fe7f74d914",
            "X-Forwarded-For": "54.86.50.139, 130.176.137.78",
            "X-Forwarded-Port": "443",
            "X-Forwarded-Proto": "https"
        }
    },
    "stage-variables": {
        "type": "object",
        "description": "ステージ変数"
    },
    "context": {
        "account-id": "",
        "api-id": "{api-id}",
        "api-key": "",
        "authorizer-principal-id": "",
        "caller": "",
        "cognito-authentication-provider": "",
        "cognito-authentication-type": "",
        "cognito-identity-id": "",
        "cognito-identity-pool-id": "",
        "http-method": "POST",
        "stage": "{デプロイ先ステージ}",
        "source-ip": "{アクセス元IPアドレス}",
        "user": "",
        "user-agent": "********************",
        "user-arn": "",
        "request-id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "resource-id": "{リソースID}",
        "resource-path": "{リソースパス}"
    }
}

event.params.header

  • リクエストヘッダーは、何もしなければそのままここに入る。
  • APIGateway>統合リクエスト>HTTPヘッダーで対応を定義すると、別のヘッダー名に変えて追加することもできる。
  • クエリパラメータや、

event.body-json

  • APIGateway>統合リクエスト>マッピングテンプレートで、リクエストのパススルーを選んだ場合、リクエストボディがそのまま入るが、JSONである必要がある。
  • JSON以外の場合は、APIGateway>統合リクエスト>マッピングテンプレートを参照。

event.stage-variables

APIGatewayのステージ変数で定義した値が入る。

{
    "stage-variables": {
        "abc": "value",
        :
    }
}


水耕栽培の成長記録システム(1) --- 構想検討 ---

概要

芽ねぎの水耕栽培を始めるにあたり、記録装置の製作を行った。



背景と目的

昨年、家庭菜園でしそベビーリーフを育てる楽しさを味わうことができた。そこで、次の作物にチャレンジしたいと思い検討した結果、芽ねぎを水耕栽培することにした。理由は以下である。

  • 芽ねぎが好き
    • シャキシャキした食感で非常にうまい
    • 海鮮系ではないにもかかわらずそれほど安くない寿司ネタなので、自宅で育てられたらちょっと得した気分になれそう
  • 室内で育てられる
    • 私自身、今まで室内で育てたことがないので、これを機にチャレンジしたい

というわけで、まず栽培にあたり水耕栽培も芽ねぎも初めてということで、栽培の様子を記録したい。そこで、まずは成長記録システムを製作することにした。



詳細

1. 参考


2. 記録装置に求める仕様

  • 培地全体を撮影し、クラウドへ送信して保存
  • 室内(周囲)環境を同時に記録

といったところだ。写真で残せると、便利なのは昨年の経験から明らかなので外せないポイント。また、周囲環境をセンシングし、のちのちの考察に生かせるとよい。他にも、成長を促す照明もつけたりしたいという欲求はあるのだが、1発目なのでシンプルに。(急に気が変わってつけるかもしれないが)


3. 設計

3.1 撮影装置

撮影装置として、以下のようなものを用意する。

まず、培地を置くベースを用意する。そこに、ポールを立て先端にカメラを固定する。カメラは、先日買ったUnit CAMを利用する。解像度が高いとは言えないのだが、事前チェックでとりあえず採用可能と判断した。また、撮影範囲に入るように、温湿度計を置く。

f:id:dekuo-03:20220211205634p:plain

3.2 全体

全体イメージは以下。後述の撮影装置で撮影した写真をクラウド上に保存する。画像保存に必要な経路は、 昨年作成した画像保存用のシステム の一部を使う。撮影した画像に映る温湿度計の数値をAWS Recognitionで検出し、Lambdaを介して温湿度値としてS3に記録する、という仕組みだ。

f:id:dekuo-03:20220211210507p:plain



まとめと今後の課題

記録装置の全体イメージが固まった。次回は製作を行う。


NuGetパッケージマネージャーが "情報を取得しています" の状態から動かないとき(Visual Studio 2013 Update5)

条件


症状

以下のように、"情報を取得しています" からずっと動かない。


やるべきこと

Visual Studioツールバー

ツール > NuGet パッケージマネージャー > パッケージマネージャーコンソール

と進み、パッケージマネージャーコンソールを立ち上げる。

立ち上げた後、

プロジェクト > NuGet パッケージ管理

と進むと、以下のようにちゃんと参照できた。理由は不明。


参考

他にも、Web上ではNuGet自体のアップデートだとか、キャッシュのクリアだとか、いろんな手段が試され解決したとかしないとか情報が錯綜しているが、私の場合これで改善した。ひとまず良しとする。