TRY AND ERROR

気になったこと、勉強したこと、その他雑記など色々メモしていきます。。Sometimes these posts will be written in English.,

Basic認証2回でちゃうとき

ハマった。。


NextJSのアプリにAWSのWAFでBasic認証かけたら、特定のページで1回目の認証をスルーした後でもう一度認証求められるようになった。

結論いうとChromeの仕様で401返されたときにBasic認証の認証済みステータスもろとも消し去るようになったのが原因。

  1. アプリ全体(ALB)にWAFでBasic認証かける
  2. ページ開いてBasic認証突破する
  3. NextJSからbackendにアプリのログインチェックのリクエスト投げて401になる(アプリのログイン失敗)
  4. アプリのログイン失敗401によりBasic認証のステータスまで消滅
  5. もう一度認証求められる

アプリの401を別のステータスに変えるとかすればうまくいくが、ちょっと嫌なのでそれはやらない。

まあ本番関係ないからいいか。

genzouw.com

Goのtestで特定のテストだけ実行する

いまさら知った話。


testifyのSuiteでいくつかのテストケースをsubtestに分けてラベル付けしてたんですが、テスト実行してもうまくフィルタリングできず正常系、異常系ともに実行される。。。

func (suite *TestSuite) TestEdit() {

         // 正常系
	suite.Run("normal", func() {
		...
	})
         
         // 異常系
	suite.Run("abnormal.validation.name", func() {
		...
	})
$ go test -v ./example -count=1 -run /TestEdit/normal


そもそもgo testの-runオプションは部分一致だった!



だから上のケースだとこれでnormalだけ実行できる

$ go test -v ./example -count=1 -run /TestEdit/^normal$


もっというとnormal、abnormalってネーミングがイケてないか。


日本語でラベルつけた方がわかりやすいんだろうけど、cliでマルチバイト打つのになんか抵抗がある。
みんなこういうとこどうしてるんだろうか

Docker for Macで開発するときのhost-container間の同期遅い問題に対するベストプラクティス(暫定)

Docker for Macでdockerつかって開発するときにhost(Mac)のディレクトリをcontainerと共有し、hostでのソース変更をcontainer側で検知してホットリロード、、、とかやってます。hostでソースをいじる理由としては、各サービスのソース(たとえばbackend, frontendなど)をhost側のエディタ環境で一元編集したいからです。コンテナ内部にvim環境作りたくない。。。


ただこれをディレクトリマウントなどでやろうとすると、結構有名なディレクトリの同期が遅い問題が発生します。
同期を高速化する施策としてdocker-syncの導入や、volumeマウント時のcached、delegatedオプションの利用を試してきましたがいまいちでした。


# docker-sync
結構長いことこれを利用してきました。速度的にはよかったんですが、動作が結構不安定なのとcpu使用率が跳ねるので脱却。

# cached、delegated
結構よさげだったが後述のmutagenの方がよかったので却下。



現状一番いいのがMutagenってやつです。
github.com



docker-compose.ymlにvolumeマウントとmutagenの設定を書いて、mutagenコマンドで起動するだけです。
mutagen-compose.ymlなどとしてmutagen使う時はそちらで起動するようにしています。

$ mutagen compose -f mutagen-compose.yml up
version: '3'
services:
  db:
    image: 'mysql:5.7'
    environment:
      MYSQL_ROOT_PASSWORD: '12345678abc' 
      MYSQL_DATABASE: 'app'
      MYSQL_USER: 'app'
      MYSQL_PASSWORD: '12345678abc'
      TZ: 'Asia/Tokyo'
    volumes:
      - ./db/sqls:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
  phpmyadmin:
    image: 'phpmyadmin/phpmyadmin'
    environment:
      - PMA_HOSTS=db
      - PMA_USER=root
      - PMA_PASSWORD=12345678abc
    ports:
      - 20000:80
  backend:
    tty: true
    build: ./backend/
    ports:
      - 20001:3000
    volumes:
      - ./backend/app:/app
  frontend:
    tty: true
    build: ./frontend/
    ports:
      - 20002:3000
    volumes:
      - frontend:/app


volumes:
  frontend:

x-mutagen:
  sync:
    defaults:
      ignore:
        vcs: true
    frontend:
      alpha: "./frontend/app"
      beta: "volume://frontend"
      mode: "two-way-resolved"
      ignore:
        paths:
      configurationBeta:
        permissions:
          defaultFileMode: 0666
          defaultDirectoryMode: 0777


mutagenはHomebrew一発で入ります。

$ brew install mutagen-io/mutagen/mutagen





なんか他にいい案あったら教えてほしいです。。。




Mutagenについてはこちらのサイトに詳しく書かれているのでかなり参考になると思います
Mutagenを使って開発環境の重たいDockerを3倍高速化する | GRIPHONE ENGINEER'S BLOG

VueJSでwatchが反応しない時

ちょっとハマった。
VueJSでwatchプロパティが反応しない場合があった。完全に反応しないのではなく特定の動作をした時に反応しなかった。
色々試してみたところv-ifなどでwatchプロパティを含む要素をdomから消した場合に反応しなかった。
逆に、domから消すのではなくv-showなどで非表示にすると動いた。

よく考えれば当たり前か。。




Struggled few moment...


Having Used VueJS, I had a problem which 'watch' property didn't react just in the specific case though It had reacted almost of all cases.The case is that the element which contains watch property is to be removed like using v-if.


Maybe if the element is not present, watch property of it cannot react at all. Contrarily It can react correctly when the element is just not visible(using v-show) rather than not exist.

Cannot get EC2 hostname from environment variables on CronJob

Assume having some EC2 instances and these have the same CronJob, When CronJobs attempts to put logs into S3 with EC2 hostname to identify which instance had put it, faced above problem and I had little bit struggled against it.
The problem occurred only in case of being run in CronJob, but not in normal script.

For example, python, you can access environment variables HOSTNAME like this.

from os
print(os.environ.get('HOSTNAME', '')) # 'ip-10-0-6-113'

But this script on CronJob cannot access HOSTNAME.

from os
print(os.environ.get('HOSTNAME', 'cannot get hostname')) # 'cannot get hostname' 


CronJobs are generally run in the different shell from one which you logged in. So it hasn't been set almost all environment variables you could access as login user. In the case in which you cannot use environment variables, you should get it with socket api.

from socket import gethostname
print(gethostname()) # 'ip-10-0-6-113'

It worked!

AWS セッションマネージャーでセッション20分制限を回避

AWS セッションマネージャーを使うとIAMユーザーでEC2にログインできるようになります。
(正確にはログインではないのですが。。)

ただ1つ問題があって、何もしない状態が20分続くとセッションが強制的に終了してしまいます。

ユーザーのアクティビティがない場合、20 分後にセッションは終了します。

セッションを終了する - AWS Systems Manager


何もしない状態(=ユーザーのアクティビティがない場合)が20分というのは、ssh繋いだまま昼飯行って放置したりする場合はもちろん、プログラム実行中で放置せざるを得ない場合なども含まれるので、今までのsshの代替として使うのはちょっと厳しいなあと思っていました。

が、この20分の制限を回避する方法がありました。


まず、セッションマネージャーでEC2インスタンスに接続する方法としては、
1) AWSマネジメントコンソール上からブラウザベースのCLIクライアントを使って接続する
2) ローカルのターミナルからSSHクライアントを通じてProxyCommandで接続する
の2つがあります。

1)を使う場合は回避できませんが、2)では以下の設定を追加することで回避できます。

# ~/.ssh/config
# デフォルト以外の名前付きプロファイルを使っている場合、--profile [プロファイル名] で指定する
host i-* mi-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession 

# ↓ これを追加
ServerAliveInterval 60


ServerAliveIntervalは指定した期間(秒)にサーバーからの応答がない場合に、応答確認をサーバーに送信するというパラメータですが、これを設定することで応答確認のpingがアクティビティと見なされるため、セッションが維持されるようです。

【Vue】CORS環境でaxiosでレスポンスヘッダが足りない時

CORSの場合、API側で色々詰めてるはずのレスポンスヘッダをダンプするとContent-Typeしか返ってこない。。
というかブラウザの開発コンソールのネットワークタブなどで見ると実際には返ってきているが、console.logでダンプした時には除去されている。
どうやらブラウザではデフォで以下のヘッダーしか見せないようにしているそうです。


Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma


サーバ側でAccess-Control-Expose-Headersヘッダをつけると、ここで指定したヘッダをjsで取れるようになります。

Access-Control-Expose-Headers: YourCustomHeaderName1, YourCustomHeaderName2



In the case of CORS, you seems to get headers only like below even if you set something other stuff on the server side.But actually you can see other headers which is correctly passed on the network tabs of developer console.
Why is that?
The reason is that browser permits you to access headers just only following fields by default. If you get other headers you could put 'Access-Control-Expose-Headers' on the server side and you explictly set your header fieldname in it.