AWS Amplify mock apiでsubscriptionを快適に使用するためにプロキシ環境を作成したよ(NextJS)
経緯
- Amplify mock api は、ローカル開発を加速させることができるので非常に便利
- しかし、現状(2022年3月)時点では、チュートリアルに書かれた方法では動作しない
- AppSyncを使いたい大きな動機が、subscriptionであり、どうしてもローカルでシミュレートしたい
対応方法
- 結局のところ、mock apiのサーバ自体はsubscriptionに対応している
- しかし、aws-sdkが未対応のため、誤ったエンドポイントに通信しており使用できない状況
- ローカルにプロキシを立てることで、sdkからmock apiへの通信を修正すれば使用できる
動作検証バージョン
- 結局のところ、mock apiのサーバ自体はsubscriptionに対応している
- しかし、aws-sdkが未対応のため、誤ったエンドポイントに通信しており使用できない状況
- ローカルにプロキシを立てることで、sdkからmock apiへの通信を修正すれば使用できる
動作検証バージョン
"aws-amplify": "^4.3.14"
"next": "^11.1.3"
詳細
mock api はsubscriptionに対応していない?
元々subscriptionが動作しないというバグがあったようだが、修正されているとのことでした。
https://github.com/aws-amplify/amplify-cli/issues/6026
しかしmock apiを動作させると分かりますが、どうもクライアントからの通信先がおかしいです。
aws-sdkの修正状況にずれが生じていることが原因のようです。
issueでは、subscription の mock api 動作時に/graphql
ではなく、/graphql/realtime
へアクセスしてしまっていることが問題のため、rewrites
などして向き先を変える必要があるとのことでした。
https://github.com/aws-amplify/amplify-cli/issues/9621
URLの書き換えをするだけなのだが。。
/graphql/realtime
へのアクセスを/graphql
に書き換える(/graphql
へのアクセスはそのままにする)だけで、問題は解決しそうです。
NextJSを使用しているなら、rewrites
の設定するだけということでパッとやってみましたが、うまく動作しませんでした。また、rewriteは気軽に使用しない方がいいという記事も発見しました。
https://zenn.dev/catnose99/scraps/91c31ee6609929
そもそも、 テスト環境作るためだけに、rewrite設定なんて入れたくない ため、別の手段を考えることにしました。
nodeモジュールでプロキシを立てる
nginxなど、プロキシアプリを別に設定することも考えましたが、NextJSプロジェクトの中で(node_modulesで)、管理できると便利だと考え、以下のようにカスタマイズしてプロキシを立てることとしました。
プロキシの方針
- node-http-proxyをベースにする
- URL書き換えのオプションがなかったのでカスタマイズする
- package.jsonにコマンド記載してyarn等で起動管理する
node-http-proxyをカスタマイズ
カスタマイズ結果はblueoath-video-ec/node-http-proxyを参照。
pathRewrite
オプションを新設して、正規表現でURL書き換えを行います。
if (options.pathRewrites && (options.pathRewrites instanceof Array)) {
for (var i = 0; i < options.pathRewrites.length; i++) {
console.log(outgoing.path);
var from = options.pathRewrites[i].from
var to = options.pathRewrites[i].to
outgoing.path = outgoing.path.replace(new RegExp(from, 'g'), to);
}
}
使い方は以下のような感じです。
var proxy = new httpProxy.createProxyServer({
...
pathRewrite: [
{ from: "^/graphql/realtime", to: "/graphql" }
],
...
});
package.jsonへの組み込み
まずは、カスタマイズしたライブラリを追加します。
package.jsonに以下のように追加してyarn install
を実行します。
"devDependencies": {
...
"node-http-proxy": "git+https://github.com/blueoath-video-ec/node-http-proxy.git",
"kill-port": "^1.6.1",
...
}
yarnを使用していますが、適宜npmなどに読み替えてください。
カスタマイズしたライブラリは適宜自分の環境にforkするなどしてください。
プロジェクトのルートにproxy.json
を配置して、プロキシサーバの起動コードを記載します。
サンプルコード
// NOTE: カスタマイズしたProxyを使用していることに注意(pathRewrite追加している)
// https://github.com/http-party/node-http-proxy
// https://github.com/blueoath-video-ec/node-http-proxy
var http = require('http');
var httpProxy = require('node-http-proxy');
var mockAPIServerPort = 20002
var proxyPort = 8015
//
// Setup our server to proxy standard HTTP requests
//
var proxy = new httpProxy.createProxyServer({
target: {
protocol: 'http',
host: 'localhost',
port: mockAPIServerPort,
path: '/',
},
pathRewrite: [
{ from: "^/graphql/realtime", to: "/graphql" }
],
changeOrigin: true
});
var proxyServer = http.createServer(function (req, res) {
proxy.web(req, res, function (err) {
// Now you can get the err
// and handle it by your self
// if (err) throw err;
console.log("http error === ")
console.log(err);
});
});
//
// Listen to the `upgrade` event and proxy the
// WebSocket requests as well.
//
proxyServer.on('upgrade', function (req, socket, head) {
proxy.ws(req, socket, head, function (err) {
// Now you can get the err
// and handle it by your self
// if (err) throw err;
console.log("ws error === ")
console.log(err);
socket.close();
})
});
console.log("mockAPIServerPort: " + mockAPIServerPort)
console.log("proxyPort: " + proxyPort)
proxyServer.listen(proxyPort);
mockAPIServerPortは、mock apiサーバのポートです。
proxyPortは、今回作成したプロキシサーバのポートです。
プロキシサーバ起動オプション追加
package.jsonに以下を追記します。
"scripts": {
...
"mock:api": "yarn kill-amplify-mock-api && amplify mock api",
"mock:proxy": "node ./proxy.js",
"kill-amplify-mock-api": "kill-port 20002 && kill-port 20003"
},
これでyarn mock:api
と打つと、mockサーバを停止して、プロキシサーバが起動されます。
アプリから使うぞ!
プロキシサーバを立てても、それだけではmock apiを使用できません。
Amplify.configure
における、aws-exports
の情報を書き換えて、エンドポイントがプロキシサーバに向くように修正が必要です。コンフィグ設定についてはここを参照。
import awsExports from '../aws-exports'
//Amplify.configure({ ...awsExports, ssr: true })
let usingProxy = awsExports
usingProxy.aws_appsync_graphqlEndpoint = 'http://localhost:8015/graphql'
Amplify.configure({ ...usingProxy, ssr: true })
上記の設定は、 ローカルデバッグの時のみ実施 する必要があります。
環境変数等で、コードの有効無効を切り替えてください。
localhost:8015
のポートは、proxy.js
で設定したproxyPort
の値を設定します。
なお、amplify mock api
実行により、aws-exports.jsの値が自動で書き変わります(mock apiの便利なところ)。
const awsmobile = {
...
"aws_appsync_graphqlEndpoint": "http://192.168.12.8:20002/graphql",
上記の:20002はmock api サーバのエンドポイントです。
これを
usingProxy.aws_appsync_graphqlEndpoint = 'http://localhost:8015/graphql'
でプロキシサーバのエンドポイントに上書き変更しています。
まとめ
AWS Amplify mock apiでsubscriptionは動作しますが、一工夫必要です。
Amplify(AppSync)は、subscriptionがあるから使ってるようなものなので、ローカル環境でmock apiが動くととても快適に開発が進められます。多少のモック環境用コードを付与する必要がありますが、やる価値はあると思いますので、ぜひお試しください。
Author And Source
この問題について(AWS Amplify mock apiでsubscriptionを快適に使用するためにプロキシ環境を作成したよ(NextJS)), 我々は、より多くの情報をここで見つけました https://qiita.com/michihiro_ota/items/04f3ae797f32bdff9e93著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .