Google Play services out of date

問題

Androidアプリ開発時以下のようなログが出力され、アプリが落ちることがあった。

Google Play services out of date. Requires xxxxxxx but found yyyyyyy

xxxxxxx や yyyyyyy バージョン番号。

解決

Google Play 開発者サービス」アプリをアップデートする。

もしかしたら、アップデート後 Android Studio を再起動する必要があるかも。 なぜかというと、アップデート後 マニフェストファイルにパーミッションを追加せよ、というエラーが出力された。でも、そのパーミッションはすでに追加されていた。Android Studio を再起動したところその問題は解消されたので。

リンク

Google Play開発者サービス - Google Play の Android アプリ

UNIXの哲学と関数型プログラミング

UNIXの哲学と関数型プログラミングは共通しているところがあるよね、というのを最近同僚と話した。

ここでいうUNIXの哲学とは

  • スモール・イズ・ビューティフル
  • 一つのプログラムには一つのことを うまくやらせる
  • ソフトウェアの挺子を有効に活用する

など(「UNIXという考え方-その設計思想と哲学」より)。

それらと、関数型プログラミングの、一つの機能に絞った小さな関数を組み合わせ、大きな関数を作っていくという部分が似ているなと。

とりわけ強くそう思うのが、UNIXでコマンドをパイプで繋げて自分の期待する結果を得るところ。関数型プログラミングだと、関数合成にあたる。

UNIXの操作に慣れている人なら、関数型プログラムもしっくりくるのでは。

不正なHTTPヘッダ

リバースプロキシとしてアプリケーションの前にnginxを置いている.

あるとき, アプリケーションにリクエストヘッダが渡らないんですけど, という問い合わせがきた.

うーん, 自分が使っている分にはヘッダは渡ってきてるんだけどな...

とりあえず, どんなリクエストを投げてるのか教えてもらったので, 試してみたところ, 報告通りヘッダが渡ってこない.

nginx を通さずに直接アプリケーションにそのリクエストを投げるとヘッダが渡ってきた. 原因はnginxにあることが判明した.

どうなっているかを把握するため debug ログを出すことにした.

/etc/nginx/nginx.conf

- error_log  /var/log/nginx/error.log warn;
+ error_log  /var/log/nginx/error.log debug;

すると以下のログが出た.

2015/01/21 09:00:16 [info] 3057#0: *2 client sent invalid header line: "X-Hoge : 1234" while reading client request headers, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "localhost"

client sent invalid header line ...不正なヘッダを送っているため、nginx で落とされているようだ.

rfc2616 によると Message Header は

message-header = field-name ":" [ field-value ]
field-name     = token

となっていて, token は

token          = 1*<any CHAR except CTLs or separators>
separators     = "(" | ")" | "<" | ">" | "@"
               | "," | ";" | ":" | "\" | <">
               | "/" | "[" | "]" | "?" | "="
               | "{" | "}" | SP | HT

となっている.

field-name と ":" の間にコントローコードやセパレータががあってはいけない.

今回は field-name と ":" の間に空白があるため, 不正なヘッダとして扱われたようだ.

nginx の設定で ignore_invalid_headers をoff にすればヘッダを落とさずにアプリケーション側に投げてくれる.

けど, まあ空白なしがRFC的に正しいので, 空白を削除してリクエストを投げてもらうことで解決.

optparse-applicative

optparse-applicative を使った。そのコードは ここ

optparse-applicative は、コマンドラインのオプションを解析するライブラリ。使い方に関してはここをよく参考にした。

オプションの解析だけでなく、必須パラメータの解析も同時に行ってくれて便利。

PHPだと同様の関数に getopt() があるが、こいつはオプションしか解析してくれない。

あと、間違えた引数を与えた場合は自動で usage を出力してくれるのも便利。

Data.Sequenceメモ

高速なキューData.Sequence.

空のキュー

Prelude Data.Sequence> empty
fromList []

キューの先頭に要素を追加

Prelude Data.Sequence> 1 <| 2 <| 3 <| empty
fromList [1,2,3]

キューの末尾に要素を追加

Prelude Data.Sequence> empty |> 1 |> 2 |> 3
fromList [1,2,3]

先頭から要素を一つ取り出す

Prelude Data.Sequence> viewl $ 1 <| 2 <| 3 <| empty
1 :< fromList [2,3]

viewl は Seq a の a を返すのではなく, ViewL a を返す。

Prelude Data.Sequence> :t viewl
viewl :: Seq a -> ViewL a

ViewL のパターンマッチ

foo :: ViewL Int -> Int
foo EmptyL    = -1
foo (x :< xs) = x

末尾から要素を一つ取り出す

Prelude Data.Sequence> viewr $ 1 <| 2 <| 3 <| empty
fromList [1,2] :> 3

viewr の場合は ViewR a が返る。

bar :: ViewR Int -> Int
bar EmptyR = -1
bar (xs :> x) = x

畳み込み

Seq a は Foldable クラスのインスタンス

import Data.Sequence
import qualified Data.Foldable as F

foo :: Seq Int -> [String]
foo = F.foldr bar []
  where
    bar :: Int -> [String] -> [String]
    bar x ys = show x : ys
*Main> foo $ 1 <| 2 <| 3 <| empty
["1","2","3"]

今のところ、これらだけでなんとかなっている。

変数のスコープ

日頃 JavaScript を書かないのがたたって、変数のスコープがどこまで有効なのかわからなかった。

問題となったのは以下のコード。変数hoycatch節でも有効なのかどうか。

try {
    var hoy = "HoyHoy";
    throw "exception";
} catch (e) {
    console.log(hoy);
}

結果はというと、有効でした。

% node hoy.js
HoyHoy

試した環境は

% node -v
v0.10.33

以上、本日のメモ。