1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Serverless Framework】serverless-offlineでcannot get nullが返ってきて表示されないときの対処法

Last updated at Posted at 2022-11-25

はじめに

私はExpressアプリケーションをコストが低いサーバレス(API Gateway/Lambda/DynamoDB)にデプロイしようと考えました。

パブリッククラウドに慣れていない+従量課金制に恐怖があったので、できる限りデプロイ前にローカルでテストできないか調査し、Serverless Framework+プラグインを使用してローカルでテストできる環境を構築することにしました。

Serverless Framework+Serverless-offline+Expressでローカルにサーバレス環境を構築したところ、ルートディレクトリにアクセスしたときに、cannot get null というエラーが発生しました。このエラー解決に時間がかかったので、記事にしておこうと思いました。

この記事の対象者

  • 同じエラーが出て困っている人
  • Serverless Frameworkを使っている人
  • サーバレスをローカル環境に構築したい人

実行環境

  • OS:Windows 11 Home 21H2
  • 言語
    • Node.js
      • version: 16.11.1
    • npm
      • version: 8.0.0
  • 使用しているライブラリ・フレームワーク
    • Express
      • version: 4.18.1
    • serverless
      • version: ^3.24.1
    • @vendia/serverless-express
      • version: ^4.10.1
    • serverless-offline
      • version: ^11.3.0

前提知識

Serverless Frameworkについて
  • Serverless Applicationを構成管理デプロイするためのツール
  • IaC(インフラのコード化)、デプロイが楽になる、Serverlessアプリケーションの管理がしやすい、プラグインが豊富でローカル環境の構築が楽にできる。
    • 類似サービス:AWS SAM
Serverless-offlineについて
  • API Gatewayをローカルで動かすServerless Frameworkの拡張機能
    • 完全にAPI Gatewayを再現しているわけではない
Expressについて
  • Node.jsにおけるWebフレームワーク
  • 基本的なミドルウェアを備え、拡張モジュールが豊富
    • 完全にAPI Gatewayを再現しているわけではない
Serverless-expressについて
  • API Gateway + lambda上でExpressアプリケーションを動かすことができるライブラリ
  • API Gateway→lambdaからくるイベントオブジェクトの変換の他、API Gateway + lambdaとの連携をよしなにやってくれるライブラリ
    • 完全にAPI Gatewayを再現しているわけではない

エラーの詳細

やりたかったこと

  • AWS Serverless環境(lambda/API Gateway/DynamoDB)をローカル環境に疑似的に構築し、デプロイ前にテストを行う。
  • serverless-expressを使ってExpressとLambdaを接続する。
  • Serverless-offline→Serverless-offline→Expressの順にリクエストを送り、ルーティング処理が行われる。

発生したエラー(上手くいかなかったこと)

Serverless-offlineとServerless-expressとの接続をする際にエラーが発生。
http://localhost:3000/dev/にアクセスしても、cannot get nullが返ってきてしまう。

↓ http://localhost:3000/dev/にアクセスした結果
serverless-offline2.png

調査したこと、思考プロセス

1 Serverless-offlineを使ったときに、サーバが立ち上がっているか確認
  • Serverless-offlineのコマンドを実行
  • serverless offlineをターミナルで実行
2 Serverless-offlineを使わないで、Expressの開発用サーバーでルーティングできるか試す
  • 問題なくルーティングできた。→Express側のルーティングの問題ではない
3 Serverless-offlineで開発サーバーを立ち上げ、他のルーティングが動くか確認する
  • 今までルートディレクトリ(/)にアクセスして表示されなかった
  • /indexのルートを追加してテスト→表示された
  • ルートディレクトリのときだけ起こるエラー
4「Serverless-offline root directory cannot get null」で検索

調査結果、エラーの発生原因

※私がまだ未熟なエンジニアですので以下の推測が間違っている場合があります。
 もし間違っている箇所があればコメントで指摘をしていただけると幸いです。

  • Serverless-offlineがServerless-expressにプロキシする際に、root directoryだけスラッシュを入れた状態でプロキシしてしまうと思われる(ちゃんとソースコード見てないので推測です)。

    • 理由
    • http://localhost:3000/dev//にはアクセスできるため、ルートディレクトリ(//)が重複している。
    • http://localhost:3000/dev//へのアクセス
      serverless-offline3.png
  • http://localhost:3000/dev/というURLでプロキシしてしまい、http://localhost:3000/dev//とスラッシュが重複してしまう。

    • serverless-offlineとserverless-express間のソースコードを見れば、原因がわかりそうではありますが。今回は割愛します。

エラーの解決法

解決方法①

  • ルートディレクトリを使用しない
    • 今回のエラーはルートディレクトリときのみ起きるエラーなのでそもそもExpress側のルーティングでルートディレクトリを使用しないようにする。

    • 例 /indexにアクセスするようにする

      // ルートディレクトリを使用しない
      // app.get("/", (req, res) => ())
      
      //代わりに/indexのようなルーティングにする
      app.get("/index", (req, res) => ())
      

解決方法②

  • ルートディレクトリを使用したいケースも存在するため、その場合はServerless.ymlにサンプルのコードを追記する。
Serverless.yml
  • Serverless Frameworkでサーバレスのインフラをコードで書くファイル。
  • ここにAWSの各リソースの設定やローカル環境時の設定等を書く。
  • インフラをコードで表した設計図
以下コードのサンプル。
provider:
  name: aws
  region: ap-northeast-1
  stage: dev
  runtime: nodejs14.x
	~~~~~~~~~~~~~~~~~~~~~~~ 以下省略

// 以下を追記する。
custom:
  serverless-offline:
    noPrependStageInUrl: true

おわりに

今回はServerlessをローカル環境で再現してるときに遭遇したエラーの解決法について書かせていただきました。実際の原因と詳しくは特定できていないので、もしご存じの方がいましたらご連絡ください。

参考にしたサイト・動画等

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?