ワンアクションでリクエストが2度実行されてしまったらやってみるべき事あれこれ


お願いだから Don't Repeat Yourself

開発中のAzure上のWebサービスで
大きな不具合を出してしまい
色々と探っていくうちに気が狂いそうになったが
やっぱりこの壁はぶつかっておくべきだったと思い
備忘録。

環境は以下。
- lang:node 8.00 + Typescript2.7.1
- FW:Koa2.5.0 + TypeOrm等
- DB:CosmosDB(MongoDB)
- cloud:Azure App Service

事の発端はazureのCosmosDBでnode上からTypeOrmのupdateOneを
試みようとしたが例外発生。
原因は更新対象が複数件データベース上にあったようで
Azureサポート様のご協力で特定することができた。
調べていくうちに一意であるはずのデータが複数件登録されていたのは
リクエストの二重送信(二重起動)が原因

改めてリクエストが複数回起動してしまう原因を探ってみた、
がこの件多くのシステムで発生しがちと思うのだが意外と資料が少ない。
諸先輩方の血と汗の結晶を下記にまとめてみた。

今回リクエストの二重送信(起動)の原因を大別すると二つ。
1.タグの属性またはjsの引数が設定されていない(いづれもURL関連)
2.フレームワークのリクエストのデフォルトタイムアウトにやられている。

1.タグの属性またはjsの引数が設定されていない件

下記で申し上げたいのは、この件ググるとfavicon.icoに関する記述が多いが
どうやらそれだけではないらしいと言うこと。
firefox特有でもなくChromeでも再現されている。

■favicon.icoへのアクセス他

ページにアクセスするとリクエストが2回飛んでしまう現象にハマった
複数回呼び出しの問題を調査する

■background-image: url()で引数urlが設定されていない

ページアクセスでリクエストが2回発生する

■上記以外の属性の設定不備

src=""とhref=""で無駄リクエストが発生する問題、ブラウザ対応状況

■その他参考リンク

Koa is being executed twice per request?
いい事をコメントしては頂いていたが私の場合これではなかった。
以下参考コメント

There are two reasons why this could happen:
First is - as already mentioned in the comments that browsers also fire a request for favicon.ico Second: some browsers do a prefentching, so before you even hit the return key, they prefetch the url when entering.

2.フレームワークのリクエストタイムアウトのデフォルト値にやられている件

結論から言うとkoaであれば、

ctx.req.connection.setTimeout( 1000 * 60 * 10 ); // 10分

とタイムアウトの時間を長めに設定することで回避できた。
一度のデバッグの時間が長くなりデフォルトの時間を越えてしまったため
この現象に出くわすこともあった。

■expressのデフォルトタイムアウトの設定1

今回解決の糸口となったコメント
このコメントにうなづいた。

I was going crazy with this duplicate request until I found this post.

■expressのデフォルトタイムアウトの設定2

■koaのデフォルトタイムアウトの設定