DEVGRU

プログラミングと競馬予想について書きます

(訂正あり) Serverless Framework で TypeScript を使うときは、aws-nodejs-typescript を使わずに serverless-plugin-typescript を使おう

(訂正)

書いたはいいが、 よくよく確認したら repository の last commit が2年前と全くメンテナンスされてない状態だったので、 こちらのほうがむしろ推奨されない方法となっていました。

なにかの参考になるかもしれないので、記事は残しておきます。

不便な記事2連発で申し訳ありません。

広告


tl; dr

sls create -t aws-nodejs-typescript -p プロジェクト名

あらまし

ちょっとしたスクレイピングをするバッチのために Serverless Framework + AWS Lambda + Node.js + TypeScript の構成で実装しようとしたが、 よく検索して出てくる方法が特定の方法に特化しすぎていて、使いづらいケースが多そうだったのでオフィシャルで説明されている方法をおすすめする。

検索するとよく出てくる方法

こちらこちらなどでは、以下のコマンドでテンプレートから生成する方法が紹介されている。

sls create -t aws-nodejs-typescript -p プロジェクト名

この方法で生成されるプロジェクトには以下の問題がある。

  • API Gateway 前提のコードになっていて、それ以外の用途で使いづらい
  • 依存が多い
  • serverless.yml ではなく serverless.ts になる

問題その1: API Gateway 前提のコードになっていて、それ以外の用途で使いづらい

生成されるコードはここの内容になる 1

github.com

見てほしいのは、 serverless.tssrc/ 以下で、どちらもガッツリAPI Gatewayを使用する設定になっている。

  provider: {
    name: 'aws',
    runtime: 'nodejs14.x',
    apiGateway: {
      minimumCompressionSize: 1024,
      shouldStartNameWithService: true,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
    },
    lambdaHashingVersion: '20201221',
  },
const hello: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (event) => {
  return formatJSONResponse({
    message: `Hello ${event.body.name}, welcome to the exciting Serverless world!`,
    event,
  });
}

serverless.tshello ハンドラーがガッチリAPI Gateway使用を前提としているので、 それ以外で定時バッチ組みたいとかのケースだとこれらのコードを削除して整える必要があり、テンプレートを使う旨味が全然ない。

むしろ意図せずAPI Gatewayに公開する危険すらあるので、それ以外の用途で使う場合以外は使うべきではない。

問題その2: 依存が多い

Lambda は依存が増えるとパフォーマンスに影響が出るので依存を減らしたいところだが、 package.jsondependencies を見ると、@middysource-map-support が入っており、不要の場合いちいち削る必要がある。

また、その下の devDependencies は実行速度に影響こそないものの、なるべく少ないほうがパッケージのメンテナンス上都合がいい。

問題その3: serverless.yml ではなく serverless.ts になる

これは良し悪しだが、 serverless.ts はあんまり使いたくない。

スキーマチェックが入るので安心できる部分はあるが、ブログなどで紹介されている記述例は9割が serverless.yml なので、いちいち変換して書く必要があるのは美味しくない。

推奨する方法: serverless-plugin-typescript を使う

serverless-plugin-typescript を使おう。

github.com

serverless ではなく prisma-labs 以下のリポジトリなので 3rd party になってしまうが、 本家からも紹介されているので、 問題なく使えると思います。

使い方は、通常のプラグインのように npm install serverless-plugin-typescript したあとに、 serverless.yml に以下を追記するだけ。

plugins:
   - serverless-plugin-typescript

あとは、handler.js ではなく handler.ts に実装するだけで良い。

バンドラの設定などはよしなにやってくれる。

細かいところは ここ を参考にすると良い

まとめ

aws-nodejs-typescript よりも、 serverless-plugin-typescript を使いましょう。

AWS Lambda実践ガイド

AWS Lambda実践ガイド

プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

  • 作者:Boris Cherny
  • 発売日: 2020/03/16
  • メディア: 単行本(ソフトカバー)


  1. プロジェクト謹製でこれなのは少し困る。

BITPointの価格取得APIに接続できたけど

このシリーズもこれで終わりにします。

team-6.hatenablog.jp

team-6.hatenablog.jp

ドキュメント読んだ通りに実装してみたつもりが接続できず、 カスタマーサポートにはサポート外と言われてみたり、と散々だったが、 どうにかつながったのでその報告。

2番めの記事の後、サポートに「サーバが生きているかどうかぐらい教えてよ」と食い下がったところ、 サーバは生きているのと、"「SockJSを使ってください」としかお伝えできません。"という超重要ヒントがもらえたので、 試行錯誤した結果、データ取得が出来るようになった。

ユーザでこれができているの、自分だけじゃないか?

以下、そのコードだが、いくつもツッコミどころがある。

const crypto = require("crypto");

const request = require('request');
const SockJS = require('sockjs-client');

const USERNAME = "your@email.com";
const PASSWORD = "your_password";

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

const sha256 = crypto.createHash('sha256');
sha256.update(PASSWORD);
const hash = sha256.digest('hex')

request.get(`https://public.bitpoint.co.jp/bpj-api/login?username=${USERNAME}&password=${hash}`,
            (error, response, body) => {
              const access_token = JSON.parse(body)['access_token'];

              const sock = new SockJS(`https://public.bitpoint.co.jp/bpj-api/twoWay?access_token=${access_token}`);

              sock.onopen = function() {
                console.log('open');
              };

              sock.onmessage = function(e) {
                console.log('message', e.data);
              };

              sock.onclose = function() {
                console.log('close');
              };
            });

ツッコミどころその1。

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";

証明書の検証エラーを黙らせる必要があった。

まじかよ…! まさかオレオレ証明書で運用しているのか?

ツッコミどころその2。

マニュアルの/loginがGETリクエスト。普通はここPOSTだろう。 しかも、passwordパラメータはSHA256で 暗号化 するように書いてあるが、常識的に考えてハッシュ値だろう。 というかハッシュ値で通った

ツッコミどころその3。

マニュアルの/loginの説明ページの右にフォームがあるが、ここに適当な値を入れてもエラーにならず、適当な値が返ってくる。

E-mailアドレスの存在チェックに使われるの防ぐためかもしれないが、そういうのはアクセス制限とかで防ぐべきではないだろうか? フォームの"パスワード"というラベルもミスリーディング。

ツッコミどころその4。

SockJSで接続できるのとWebSocketで接続できるのは別。マニュアルのエンドポイントがhttpsしか書いてないのでいろいろおかしいと思ったが、どうやったらSockJS使うと分かるというのか。

純粋なWebSocketで繋がるかどうかを検証するためwsで書きなおしてみたい気もするが、動いたところでなんの特もないのでこのあたりでやめておく。

結論、こんなわかりづらいAPIとそのドキュメントを提供している時点で安心して使うことはできない。お金を動かすに足らないレベルの信頼性である。特に証明書。

もし使うならそれなりの覚悟を持って使ったほうが良い。

WEB+DB PRESS Vol.71

WEB+DB PRESS Vol.71

  • 作者: 竹迫良範,Jxck,はまちや2,相澤歩,柴田博志,池田尚史,梅澤雄一郎,九岡佑介,近藤宇智朗,佐藤鉄平,mala,川添貴生,じょさん,後藤秀宣,藤原俊一郎,奥野幹也,堤智代,森田創,中島聡,A-Listers,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2012/10/24
  • メディア: 大型本
  • 購入: 15人 クリック: 180回
  • この商品を含むブログ (10件) を見る

HTML5 Web標準API バイブル

HTML5 Web標準API バイブル

BITPointの価格取得APIに接続できない

BITPointの口座も開設できたので、システムに組み込もうとしたのだが、 APIの叩き方が悪いのか、それともサーバが落ちているのか、WebSocketのopenイベントが発火しない。 openイベントが発火しないままではsendが送れない。

こんな感じのコードを書いているが、イベントはどれも発火しない。 どうやらリクエストに対してサーバがレスポンスを送っていないようだ。

const WebSocket = require('ws');

const ws = new WebSocket('ws://public.bitpoint.co.jp/bpj-api/leverageTwoWay?access_token=mytoken');

ws.on('connection', (e) => {
  console.log(e);
});

ws.on('error', (e) => {
  console.log(e);
});

ws.on('message', (message) => {
  console.log(message);
});

ws.on('open', () => {
  console.log('open!');
  ws.send(JSON.stringify({
    currencyCd1: 'BTC',
    currencyCd2: 'JPY',
  }));
});

とりあえず問い合わせからサーバが動いているかを問い合わせているが、 落ちている気がする。

または上記のコードが間違えている可能性もあるが、ドキュメントの書き方が微妙でイマイチ正しいか確信が持てない。

https://public.bitpoint.co.jp/bpj-api/api#

とりあえずこの問題が解決するまではBITPointの利用はお預けだ。