nginxでリバースプロキシしているときにupstreamからのレスポンスヘッダを書き換える。

やりたいこと

いろいろあって、nginxでリバースプロキシしているときに、upstreamから渡ってくるlocationヘッダの中身を書き換えないといけない場面に出くわしました。
普通ならproxy_redirectでどうにかするものですが、upstreamが返してくるlocationヘッダが自分の管理しているサイトとは全然別のところで、それをどうにか書き換えないといけません。ちなみにいじっている環境はモジュールが導入できないので、デフォルトで有効になっている機能でどうにかする必要があります。

やりたいことを図にするとこんな感じですね。

これを

upstream--(Location: http://example.com?hogehoge)--> nginx--> クライアント

こうしたい。

upstream--(Location: http://example.com?hogehoge)--> nginx (Location: http://example.jp?hogehoge)--> クライアント

失敗した方法

最初「if使って書き換えればいいじゃん」と思って試したのが以下。

location / {
  if ($upstream_http_location ~ example.com(.*)){
     proxy_hide_header location;
     add_header location http://example.jp$1;
  }
}

おそらくifの評価タイミングが$upstream_http_locationに値が設定される後ではなく前のため、どう頑張っても評価がfalseになってしまいました。そもそもlocation内でifを使うのは事故の元なのであんまりよくないです。
If Is Evil | NGINX

期待通りに動作した方法

じゃあmapならどうだと思って試したのが以下。

map $upstream_http_location $location{
  ~example.com(.*) http://example.jp$1;
  default $upstream_http_location;
}
location / {
  proxy_hide_header location;
  add_header location $location
}

動きました。ifは評価タイミングがクライアントからリクエストを受けた直後で、mapはレスポンス返す直前なのかな…。そこは理解できていません。
Module ngx_http_rewrite_module
Module ngx_http_map_module

twitter系のアプリが軒並み死んでいたので復旧させました。

Twitter が OAuth 認証時 Callback URL をチェックするようになったみたい – プログラミング生放送
Action REQUIRED – Sign in with Twitter users must whitelist callback URLs – Announcements – Twitter Developers

何だこの仕様変更。ほぼすべてのアプリで設定が適当(httpsがhttpになってたりURLが違ったり)だったため修正しました。最初upicoが使えないとのご連絡を頂きまして、トークン払い出しきったと思って一時対処的にtwimageのキーを設定してたのですが、結局原因が全然違ったという。
コードに修正の入る仕様変更だった場合、もう直す時間も気力もないと思ってたので、簡単に修正できてよかったです。

インドのプネーでAISのSIM2Flyを使ったみた雑感とか。

仕事でインドのプネーに1週間ほど滞在していました。
Pokemon Goでどうしてもサニーゴを捕まえたかったのと、人とコンタクトをとる手段(主にLINE)が使用不能になると命に関わりそうだったので、事前にAmazonでSIMを購入しました。

使用感

インドだとAirtel回線を使用して繋ぐことになります。使用感ですが、特に問題なく繋がり問題なく使えました。が、4G回線でも遅い気がしました。LINEでもテキストメッセージは問題なく送信できるけど、写真は厳しいといった状態ですね。Amazonのレビューにもある通り、バスでの移動中に時たまエラーで繋がらなくなったりしましたが、機内モードから戻すと掴んだので許容範囲かなという感じです。いつでもどこでもスマホでネットが使える日本のインフラに感謝の気持ちがわきました。

ハードとの相性とか

nexus5, nexus5x, zenfone3, nova liteで試しましたが、nexus5とnexus5xでは2G回線しか掴まないか、接続時にエラーが出て(アンテナのアイコンに×マークが付く)ほぼ使い物にならない状態だったので、このSIMを使用して5と5xをインドに携帯するのはおすすめできません。LGのハードに問題があるのかもしれませんが、はっきりとした原因は不明です。5も5xもどっちも使えなかったのでOSの問題ではない気がします。他の機種では問題なく使えました。iPhoneはわかりません。

インド行った感想

バスで走ってるといたるところにAirtelのお店があってインドすげーなーと思いました。サニーゴは滞在最終日にバスで空港に向かってる途中で根性で捕まえました。全然出てくれなくてだいぶ諦めてたのでめっちゃうれしいです。
Phoenix Market Cityにちょっとだけ寄ったのですが、Pixel2の展示会やってました。触ってる暇がなかったのは残念でした。買って帰ろうかなーと思ったのですが、インドで買っても普通に高い(日本円で8万くらいする)のでやめました。

Pixel2の広告

道路状況が本当に最悪(しぬほど揺れるのとスピードブレイカーの凸段差で酔う)なのと、運転手が普通にアホみたいにスピード出すので死ぬかと思いました。道路に牛も人も普通に突っ込んでくるしバイク乗ってる人ほぼ全員ノーヘルだし車線は存在しないし信号はないしとにかくやべえ。現地の人曰く、プネーはまだましで、デリーが最高にクソらしいです。これ以上クソだったらほんと死ぬのでデリーは行きたくないなと思いました。
あと、滞在最終日の朝にnexus5xが突然うんともすんともいわなくなってブートローダーすら起動しなくなりました。LG製品はもう二度と買いたくないです。

[解決済み] Nature Remoは一度メールアドレスを認証させてしまうと変更時にめっちゃくちゃめんどくさい。

表題の通り、というかガジェット系は不具合あっても割とイライラせずに使用するタイプだと思ってるのですが、これはさすがに改善要求したいレベルで仕様がひどかったです。散々発売延期してコレかよ…。

2018/05/29 追記

2018/3/13のアップデートでログアウトとメールアドレスの編集ができるようになったため、以下の問題は解決可能です。

あらまし

Nature RemoとGoogle Home miniを買ったので、IFTTTで連携しようと思いました。nexus5xでアプリをインストールし、メールアドレスAでRemoのアカウント登録を実施し、セットアップ→家電の登録まで済ませました。
次にIFTTTでGoogle Assistantを認証し、Nature Remoの連携も実施しました。これで晴れて音声で家電が操作できるようになりました。やったぜ。ここまではめっちゃくちゃ簡単でしたし、コーディング無しでここまでのことができるのはかなりすごいです。

問題となる操作

ここまでセットアップしたところで、どうしても他のメールアドレスを使用してRemoのアプリ、及びRemoを使用しなければならない事情が発生しました。メールアドレスAではなく、メールアドレスBを使用して最初から全部やり直します。
とりあえずNature Remoの背面ボタンを押してハードリセットしました。壁に貼ってるので、リセットボタンは背面ではなく側面につけてほしかったです。
なお、以降に書いた操作はnexus5x 1台で行っています。

何が問題になるか

  • Nature Remoのアプリにサインアウトの方法がない。(少なくともAndroidアプリにはない)

単純にアプリをアンインストールするだけだと設定値が残存するため、アプリデータを削除してからアンインストールしないとログアウトできません。というか登録済みのアカウントってどこで削除すればいいんでしょうか…。

  • IFTTTとConnectする時に、Connect先のRemoアカウントが古い方になる

  • OAuth認証時に、認証先のRemoアカウントがわからない

IFTTTとRemoの連携をIFTTTのServicesから削除した後、RemoにConnectしなおす場合、ブラウザでOAuth認証するアカウントの対象が古いメールアドレスになります。TwitterのようにOAuth認証画面で認証先のアカウントを確認+変更できれば良いのですが、アカウントがどれなのかもわからないし、認証画面でログアウトもできないので、仕方なくブラウザのキャッシュを全消しして対処しました。
これがかなりクソで、Connect後にServicesを確認しないとどのRemoアカウントと連携してるのかわからないので、古い方のRemoアカウントと連携しているのに気づかず、いつまでたってもRemo側の設定値がIFTTTから読めなくてめっちゃくちゃイライラしました。30分くらいハマった時点でやっと気づいたのですが、ユーザのせいって言われると納得行かない仕様だと思いました。

想定していない操作だったのかもしれませんが、メールアドレス変わったときとかどうすればいいのかわからないし、改善してほしいです。

上記仕様とアプリ自体が初期のPokemon GOレベルで不安定なのを除けばRemo自体は便利です。エアコンも簡単に制御できますし、IRKitで問題だったLEDもまぶしくないし、早くREST API公開してほしいなぁと思います。公開されましたね。

tag.retrorocket.biz(はっしゅたんぐら。)のデータが飛びました。

物理的に壊れたのとバックアップも取ってなかったので復旧できません。ほんとすいません。
tag.retrorocket.biz(はっしゅたんぐら。)については利用者が片手で数えるくらいしかいないので、Raspberry Pi 3で運用していたのですが、引っ越しの時にSDカードがぶっ壊れたようでサルベージすらできませんでした。
とりあえずサービス自体はさくらVPSに移行しましたが、IFTTTで同じことができるはず(実際にできるかどうかは試してません)なので、今後はIFTTTの使用をおすすめします。