GNU GuileのHTTPレスポンスで日本語が文字化けする問題の解決法
GNU Guile でHTTPレスポンスを処理するプログラムを書いていて、 日本語が文字化けする問題ではまって1時間くらい時間を溶かしました。
公式ドキュメントをみれば分かるというのはそうなのですが、 求めている情報がどこにあるのかよく分からず迷走したので、 解決方法を備忘録として残しておきます。
結論としては、ただの port のエンコーディングの問題だったのですが、
手元のファイルを call-with-input-file
などで開いたときには、
問題なく日本語を扱えることから port 側の問題だと思わず、
HTTP関連特有の問題かと思って調べたのではまりました。
1. 前提: GNU Guile の http クライアントの使い方
GNU Guile Reference Manual の 7.3 HTTP, the Web, and All That に Guile で HTTP プロトコルを扱う方法が記載されています。
たとえば、ある url に対して POST メソッドでリクエストを投げる場合は次のようにします。
(define response (http-request uri #:body body #:method 'POST #:streaming? #t))
http-request
の戻りとして response というオブジェクトが得られます。
これを処理すれば、HTTPネットワーク上のリソースを扱うことができます。
(response-body-port response)
でテキストのポートが得られ、
body 部を読み取ることができるのですが、
このときに日本語が文字化けしてはまりました。
2. 解決方法: port のエンコーディングを確認し変更する
GNU Guile Reference Manual の 6.12.3 Encoding の節に記載があるように、
port にはエンコーディングの仕方が設定されており、
GNU Guile では port-encoding
でポートのエンコーディングの確認、
set-port-encoding!
でポートのエンコーディングの変更ができます。
私の場合はポートのエンコーディングが ISO-8859-1
になっていたせいで、
文字化けが発生していました。
scheme@(guile-user)> (port-encoding (response-body-port response))
$87 = "ISO-8859-1"
これを set-port-encoding!
を使って UTF-8
にすれば解決です。
scheme@(guile-user)> (define port (response-body-port response)) scheme@(guile-user)> (port-encoding port) $89 = "ISO-8859-1" scheme@(guile-user)> (set-port-encoding! port "UTF-8") scheme@(guile-user)> (port-encoding port) $90 = "UTF-8"
3. おわりに
GNU Guile の日本語の情報を増やし、 GNU Guile を使ってみようと思う人が増えればと思い記事にしてみました。
GNU Guile ではまってもドキュメントを漁ればだいたいなんとかなるので、 GNU か Scheme が好きな人は是非使ってみてください。
今後も、GNU Guile ではまったことを記事にしていき、 日本語の知見を増やしていければと思います。