✖
✖
先々週も先週も今週も、週末なぜかひたすら寝ていた。無限に疲れている。
関連エントリー
- 体調不良 金曜あたり頭がぼーっとするなぁと思っていたら、土曜日午後あたりから急激に身体もだるくなってひたすら寝ていた。
- ✖ 先週末に奈良に行った。 子供が歩く前に一回どっか行っておこうということで、1週間前ぐらいに急に予定を決めて1泊した。 いったところ 1日目 春日大社 東大寺 (大仏殿) 法隆寺 2日目 大神神社 (大...
- 最近の体調不良 先週は1日おきぐらいにちょいちょい調子が悪くて1日は休んだ。よくなったかと思ったら、月曜日の昼ぐらいから劇的に調子が悪くなり38.3℃ぐらいまで熱があがる。熱があがっている間って、あまりにもだるくて身...
- 先週がとにかくひどかった 日曜日の夕方ぐらいから、かなり体調が悪化して熱が出てきた。 子供も午後から熱が出て高熱に。 月曜日の朝、子供がけいれんを起こし救急車を呼ぶ (5分経過時点で119にかけたが、電話が終わった直後にけいれ...
- 無線 まだ2局ほど 599BK 形式でやっている局を呼んだだけで、それ以上のことはできてない。近畿あたりの局を呼んでみたりしたけど、パイルアップになっていないにも関わらずとってもらえなくて、聞こえるけど届か...
サイトの最適化
HTTP2 化に伴なって、サイト全体の最適化を行ないました
依存の整理
もはや jQuery なしでも簡単に書けそうなスクリプト部分から jQuery 依存を抜きました。また、JSDeferred を Promise で置き換えました。
script 要素の async / defer
script 要素については必要に応じて async や defer をつけるようにし、基本的に外部スクリプトでブロックする可能性を排除しました。
async は script 要素同士で独立している場合無条件につけられます (非シーケンシャル)。defer はページのDOMが構築されたあとに実行されるように遅延されます (シーケンシャル)
defer は DOMContentLoaded 直前にまとめて呼ばれるようです。
外部ライブラリを自分でホスト
外部ライブラリをCDN経由でロードしている部分がありましたが、TLS セッションの無駄遣いな気がするので、自分でホストするように変えました。自分のホストであれば HTTP2 のセッションが生きているので無駄な処理が減りそうです。
動的圧縮から静的圧縮に
h2o で compress: ON とすると accept-encoding に応じて gzip か br で動的に圧縮してクライアントに返却してくれます。
しかし殆ど変更されないライブラリみたいなものは動的にやるのがもったいないので、静的に圧縮するようにしました。特に brotli は圧縮処理が遅い感じなので意味がありそうです。
h2o 的には file.send-compressed: ON にしって、filename.js.gz と filename.js.brを置くようにします。
.gz と .br をつくるスクリプト
以下のようなスクリプトを作っておくと、指定したファイルの .gz と .br を作れて便利です。
静的に作っておけば、特に VPS のスペックが非力だと相対的に効果が高いはずです。
#!/bin/sh
for f in "$@"
do
echo "$f"
gzip --best < "$f" > "$f".gz
bro --quality 10 --input "$f" --output "$f".br
done brotli について
h2o は brotli に対応していて、accept-encoding: br なときはオンデマンドも br を返すみたいです。
ただ、brotli は chrome に実装済みといっても flags で有効にしないとまだ使えないみたいです。
Firefox 45 は標準で accept-encoding: br を吐くようです。
ブログシステムでのキャッシュ
今まで表示のたびに DB からひいてきてテンプレート処理を行っていましたが、キャッシュするようにしました。もともとそこまで遅いわけではないのですが 、一応これも効果がありました。
ただ、キャッシュを入れるとキャッシュ無効化の処理のために考えることが大変増えます。今のところあまり筋の良い実装ではないのですが、一応動いています。
MathJax のサーバサイド化
[tech] サーバーサイド MathJax で数式表示を高速化する | Fri, Apr 8. 2016 - 氾濫原 別エントリにしました。
いろいろやった結果
キャッシュなしの状態でロードして、DOMContentLoaded まで 300ms を切るぐらいにできました。ただし onload までは2秒〜3秒かかっています。onload まで遅いのは画像のサイズが大きいというのと、あとは主にアドセンスのせいです。
同じ環境で www.google.co.jp のDOMContentLoaded を測ると 170ms ぐらいでしたので、要素数などを比較するといい線まできている気がします。
さらにできることは?
いわゆる minify をやっていないので、これをやる余地がまだあります。しかし結構面倒です。そしてたとえ削れても数kBなので、意味があるのか疑問を持っています。
関連エントリー
- このサイトのキャッシュ キャッシュの持ちかたを変えて、圧縮 (gzip) して持つように変えた。キャッシュを返すときは gzip ずみのをそのまま返すように。 gzip 非対応ブラウザでおかしくなる気がするけど、昨今そんなブ...
- HTTP2 で何をサーバープッシュすべきか 意外と何をプッシュすべきか悩んだのでひとまず現時点での自分の結論をまとめました。 CSS は必ずプッシュ・JSは場合による サイトの構成によりますが、ページの表示に必要なものは全てプッシュするべきのよ...
- しょぼい個人サイトのキャッシュ 殆どアクセスがないサイトは、ファーストアクセスでキャッシュを作るようなサーバサイドキャッシュの戦略が全く意味がないので、バッチで予めキャッシュを作っておくみたいなことが必要そうだなと思い、そういうスク...
- h2o で特定のファイルがオンザフライ圧縮されないとき h2o は compress: ON にすると、レスポンスに accept-encoding に応じたオンザフライな圧縮が有効になります。ただしデフォルト状態ではcontent-type が text...
- h2o の casper を一時的に無効にする h2o の casper (cache-aware server-push) を有効にしていると、force reload したときでも push されなくなってしまって、だんだん混乱してきます。YA...
サーバーサイド MathJax で数式表示を高速化する
このサイトでは数式を本文中に TeX 形式で書いて MathJax で処理させています。↓ こういうやつです。ベクターなので昨今の高解像度事情でもいい感じに綺麗に表示できます。
これはクライアントサイドで本文中の TeX フォーマットを探して全部 SVG とかに置き換えていくのですが、これがなかなか重い処理です。
特にスマートフォンの場合、数式がまともに表示されるまで5秒〜10秒ぐらいかかるので、それまでモヤモヤした感じになります。
さらにいえば、これは非同期で変換をかけているのでロード直後にリフローが頻発することになります。
ということで、これらの問題をなんとかしたいので、標題のようにサーバサイドで MathJax を使ってみるようにしてみました。
このサイトははてな記法で書いたエントリを保存時にHTMLに変換し、変換済みをDBにいれて、表示のときはそれを出しているだけです。なので、保存時に MathJax を通して本文中の数式を埋め込み SVG に変換するようにします。
HTML の断片をうけとって MathJax にかける HTTP サーバ
幸い MathJax-node という node.js 上で動かせる MathJax があったので、これをそのまま使い、http.Server でラップして、ブログシステムとは別に API サーバを立ち上げました。
#!/usr/bin/env node
var mjAPI = require("mathjax-node/lib/mj-page.js");
mjAPI.start();
mjAPI.config({
tex2jax: {
inlineMath: [["\\(","\\)"]],
displayMath: [ ["$$", "$$"] ]
},
extensions: ["tex2jax.js"]
});
var http = require('http');
http.createServer(function (req, res) {
var html = [];
req.on('readable', function () {
var chunk = req.read();
console.log('readable');
if (chunk) html.push(chunk.toString('utf8'));
});
req.on('end', function() {
console.log('end');
console.log('html', html);
mjAPI.typeset({
html: html.join(""),
renderer: "SVG",
inputs: ["TeX"],
ex: 6,
width: 40
}, function (result) {
console.log('typeset done');
console.log(result);
res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
res.end(result.html);
});
});
}).listen(13370, '127.0.0.1');
console.log('Server running at http://127.0.0.1:13370/'); ブログシステムからは保存時にこのAPIを呼んでHTMLをフィルタしてDBに保存するようにしました。
ハマりどころ
動的な MathJax だと、ページのコンテナサイズから適切な幅を計算してくれるのですが、サーバサイドだとそれができませんので、適切な横幅を自分で指定する必要がありました。
スマートフォンでの閲覧を考えると、width: 40 ぐらいにして、念のため CSS で svg { max-width: 100% } とかを入れておくとよさそうです。width が大きいと、数式ごとのフォントサイズが変わりまくって大変うっとおしいです。
MathJax-node の速度
MathJax-node はなぜかものすごく遅いです。ライブラリロード済みでも10秒ぐらいかかります。そもそも起動も遅いです。オンデマンドでやるのは無理そうなレベルです。
MathJax の JS のロードを抑制
これに伴なって、MathJax を使わなくても良さそうな場合、JSのロードすらやめるようにしました。
所感
MathJax の JS は2段階ぐらいでロードされるので RTT が長いほど不利になります。サーバサイドでやってしまえばJSを転送する必要も実行する必要もなくなるのでエコです。おかげでロードが結構早くなりました。
しかもページロード直後から数式が完全な形で表示されるので、ページに数式がある場合、体感的な速度は数倍に感じます。
関連エントリー
- ブログシステムの HTML 生成を効率化 そろそろやることなくなったので minify などをやることにしました。 ただ、ブログシステムの出力の最後ほうでページごとに全体を minify すると、全体としてどうしても処理に時間がかかってしまい...
- HTML5 の svg 要素 を canvas に描く方法 こうする async function loadAsImage(svg) { return new Promise((resolve, reject) => { const svgXml = new ...
- 日記に楽譜を表示できるようにした。 日記に楽譜を表示できるようにした。 この日記ははてな記法で書いてるので、super pre 記法でABC記譜法を書くと、該当箇所を abcjs でレンダリングしなおすという実装にした。 MathJax...
- Server::Starter を node.js のサーバ起動に使う Server::Starter は hot deploy 用の汎用スーパーデーモンで、Perl で書かれています。h2o の起動にも使われているのでみなさんおなじみでしょう! Server::Star...
- 正規表現からそれにマッチするランダム文字列を生成する String_random.js var randomUrl = String_random(/http:\/\/[a-z]{3,8}\.example\.com\/([a-z]+\/){3}/); console.log(rando...
h2o のログ設定 (logrotate.d)
ログの設定を stdout のままにしていたので rotate するように設定しました。(Ubuntu 12.04.5 LTS)
h2o の設定
sudo mkdir /var/log/h2o sudo chown www-data:adm /var/log/h2o/
YAML の参照を使うとログフォーマットを使いまわせてよいです。まず global に
access-log: &ACCESSLOG
path: /dev/null
format: "..." と書いて、あとは各ホストで path を上書きする形で設定します。
access-log:
<<: *ACCESSLOG
path: /var/log/h2o/host.access.log なおこのYAML参照は h2o 2.0.0 からのサポートのようです。
logrotate の設定
# /etc/logrotate.d/h2o
/var/log/h2o/*.log {
daily
missingok
rotate 90
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
svc -h /service/h2o
endscript
} h2o は daemontools で管理しているので、postrotate では svc を呼んで SIGHUP を送っています。
一旦状態を確認します
sudo logrotate -dv /etc/logrotate.d/h2o
全ログファイルが log does not need rotating になってるはずです。実際に一度実行します
sudo logrotate -v /etc/logrotate.d/h2o
/var/lib/logrotate/status を見ると該当するログファイルが記録されているはずです。日付を一日戻して再度実行するとローテートされることが確認できます。
関連エントリー
- Ubuntu 16.4 LTS クリーンインストールして引越 カスタムOSインストールガイド - Ubuntu 16.04 – さくらのサポート情報 を見ながらインストールまでやる。 旧サーバと同じホスト名にしてDNSをふりかえたいが、DNS やホスト名まわりは...
- h2o を systemd 管理下にした 徐々に daemontools 依存を外していってるが、とりあえず h2o を systemd に管理にすることにした。どうも daemontools だと annotate-backtrace-sy...
- 現在の h2o.conf.yaml 今のこのサイトの h2o.conf.yaml です。HTTPS (443) のみを処理しています。HTTP (80) は nginx で受けていて、HTTPS 対応ホストに関しては nginx からは...
- Let's encrypt の自動更新 以下のようなスクリプトを置いて月イチの cron で更新するようにしました。証明書を更新したあと h2o を restart しています。 #!/bin/sh # sudo crontab -e # ...
- h2o の casper を一時的に無効にする h2o の casper (cache-aware server-push) を有効にしていると、force reload したときでも push されなくなってしまって、だんだん混乱してきます。YA...
Let's encrypt の自動更新
以下のようなスクリプトを置いて月イチの cron で更新するようにしました。証明書を更新したあと h2o を restart しています。
#!/bin/sh
# sudo crontab -e
# MAILTO = cho45
# PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
# 25 14 6 * * /srv/www/renew-cert.sh
BIN=/home/cho45/project/letsencrypt/letsencrypt-auto
$BIN certonly --webroot -w /srv/www/www.lowreal.net --renew-by-default -d www.lowreal.net
$BIN certonly --webroot -w /srv/www/lowreal.net --renew-by-default -d lowreal.net
$BIN certonly --webroot -w /srv/www/cho45.stfuawsc.com --renew-by-default -d cho45.stfuawsc.com
svc -h /service/h2o
関連エントリー
- h2o を systemd 管理下にした 徐々に daemontools 依存を外していってるが、とりあえず h2o を systemd に管理にすることにした。どうも daemontools だと annotate-backtrace-sy...
- Ubuntu 16.4 LTS クリーンインストールして引越 カスタムOSインストールガイド - Ubuntu 16.04 – さくらのサポート情報 を見ながらインストールまでやる。 旧サーバと同じホスト名にしてDNSをふりかえたいが、DNS やホスト名まわりは...
- 現在の h2o.conf.yaml 今のこのサイトの h2o.conf.yaml です。HTTPS (443) のみを処理しています。HTTP (80) は nginx で受けていて、HTTPS 対応ホストに関しては nginx からは...
- lowreal.net のHTTP2/HTTPS 化を実施 全部 HTTPS 対応にしてリダイレクトかけるようにしました。 cho45.stfuawsc.com は既に HTTPS にしてありました。こちらは nginx に letsencrypt の証明書を...
- h2o のログ設定 (logrotate.d) ログの設定を stdout のままにしていたので rotate するように設定しました。(Ubuntu 12.04.5 LTS) h2o の設定 sudo mkdir /var/log/h2o sud...
現在の h2o.conf.yaml
今のこのサイトの h2o.conf.yaml です。HTTPS (443) のみを処理しています。HTTP (80) は nginx で受けていて、HTTPS 対応ホストに関しては nginx からはリダイレクトしています。
- アクセスログフォーマットを LTSV に
- ログフォーマットを YAML の参照で全ホストで共有
- rewrite rule
- Strict-Transport-Security (HSTS)
- 一旦 https でアクセスしてきたクライアントに対して以後 http でのアクセスをさせない
- 本来はセキュリティのためだが、リダイレクトを一回減らせるのでパフォーマンス的にも一応得
- "/.well-known": をバインド
- letsencrypt のホスト検証に使われる
設定の際参考になれば幸いです。
user: www-data
access-log: &ACCESSLOG
path: /var/log/h2o/access.log
format: "time:%t\thost:%h\treq:%r\tstatus:%s\tsize:%b\treferer:%{Referer}i\tua:%{User-Agent}i\tcache:%{X-Cache}o\truntime:%{X-Runtime}o\tvhost:%{Host}i\tconnect-time:%{connect-time}x\trequest-header-time:%{request-header-time}x\trequest-body-time:%{request-body-time}x\tprocess-time:%{process-time}x\tresponse-time:%{response-time}x\tduration:%{duration}x\thttp2.stream-id:%{http2.stream-id}x\thttp2.priority:%{http2.priority.received}x"
error-log: /dev/stdout
http2-reprioritize-blocking-assets: ON
ssl-session-resumption:
mode: all
hosts:
"lowreal.net:443":
access-log:
<<: *ACCESSLOG
path: /var/log/h2o/lowreal.net.access.log
http2-casper: ON
compress: ON
listen:
port: 443
ssl:
certificate-file: /etc/letsencrypt/live/lowreal.net/fullchain.pem
key-file: /etc/letsencrypt/live/lowreal.net/privkey.pem
header.add: "Strict-Transport-Security: max-age=31536000"
header.add: "X-Content-Type-Options: nosniff"
header.add: "X-UA-Compatible: IE=Edge"
paths:
"/":
reproxy: ON
mruby.handler: |
require "/srv/www/rewrite_rules.rb"
lambda do |env|
RewriteRules.rewrite(env) do
rewrite '/favicon.ico', '/images/favicon.ico', :break
rewrite '/apple-touch-icon.png', '/images/apple-touch-icon.png', :break
rewrite %r{^/2005/colors-canvas\.xhtml$}, '/2005/colors-canvas.html', :permanent
rewrite %r{^/2005/colors-canvas$}, '/2005/colors-canvas.html', :permanent
rewrite %r{^/logs/latest$}, '/', :permanent
rewrite %r{^/logs/latest.rdf$}, '/feed', :permanent
rewrite %r{^/logs/latest.atom$}, '/feed', :permanent
rewrite %r{^/latest\.rdf$}, '/feed', :permanent
rewrite %r{^/blog/index\.(rdf|atom)$}, '/feed', :permanent
rewrite %r{^/logs(/.+?)(\.(rdf|atom))$}, '/feed', :permanent
rewrite %r{^/logs(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/blog(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/photo$}, '/photo/', :permanent
rewrite %r{^/(\d\d\d\d/\d\d(/\d\d)?)$}, '/\1/', :permanent
rewrite %r{^/\d\d\d\d/$}, '/', :redirect
rewrite %r{^/view-img(/.+?)$}, '\1', :permanent
rewrite %r{^/(\d\d\d\d/([^\d]|\d\d[^/]).*)}, '/files/\1', :break
end
end
proxy.reverse.url: http://localhost:5001
proxy.preserve-host: ON
"/files":
file.dir: /srv/www/lowreal.net/files
"/images":
file.dir: /srv/www/lowreal.net/Nogag/static/images
"/css":
file.dir: /srv/www/lowreal.net/Nogag/static/css
"/js":
file.dir: /srv/www/lowreal.net/Nogag/static/js
"/lib":
file.dir: /srv/www/lowreal.net/Nogag/static/lib
"/.well-known":
file.dir: /srv/www/lowreal.net/.well-known
"www.lowreal.net:443":
access-log:
<<: *ACCESSLOG
path: /var/log/h2o/www.lowreal.net.access.log
http2-casper: ON
compress: ON
listen:
port: 443
ssl:
certificate-file: /etc/letsencrypt/live/www.lowreal.net/fullchain.pem
key-file: /etc/letsencrypt/live/www.lowreal.net/privkey.pem
header.add: "Strict-Transport-Security: max-age=31536000"
header.add: "X-Content-Type-Options: nosniff"
header.add: "X-UA-Compatible: IE=Edge"
paths:
"/":
reproxy: ON
mruby.handler: |
lambda do |env|
link = [
'/styles/201002/201002.css',
'/js/site-script.js',
].map{|p| "<#{p}>; rel=preload"}.join("\n")
case env['PATH_INFO']
when "/"
if (env['HTTP_ACCEPT_LANGUAGE'] || '') =~ /ja/
return [307, {"x-reproxy-url" => "/index.ja.html", "link" => link }, []]
else
return [307, {"x-reproxy-url" => "/index.en.html", "link" => link }, []]
end
when "/index.ja.html", "/index.en.html"
return [399, {"link" => link }, []]
end
return [399, {}, []]
end
file.dir: /srv/www/www.lowreal.net
# file.index: [ index.en.html ]
"cho45.stfuawsc.com:443":
access-log:
<<: *ACCESSLOG
path: /var/log/h2o/cho45.stfuawsc.com.access.log
listen:
port: 443
ssl:
certificate-file: /etc/letsencrypt/live/cho45.stfuawsc.com/fullchain.pem
key-file: /etc/letsencrypt/live/cho45.stfuawsc.com/privkey.pem
header.add: "Strict-Transport-Security: max-age=31536000"
header.add: "X-Content-Type-Options: nosniff"
header.add: "X-UA-Compatible: IE=Edge"
paths:
"/":
file.dir: /srv/www/cho45.stfuawsc.com
redirect:
status: 301
url: "/niro/"
"/niro/":
proxy.reverse.url: http://localhost:5001/niro/
proxy.preserve-host: ON
"/tmp":
mruby.handler: |
require "htpasswd.rb"
Htpasswd.new("/srv/www/.htpasswd", "Restricted")
file.dir: /srv/www/cho45.stfuawsc.com/tmp
関連エントリー
- Let's encrypt の自動更新 以下のようなスクリプトを置いて月イチの cron で更新するようにしました。証明書を更新したあと h2o を restart しています。 #!/bin/sh # sudo crontab -e # ...
- h2o のログ設定 (logrotate.d) ログの設定を stdout のままにしていたので rotate するように設定しました。(Ubuntu 12.04.5 LTS) h2o の設定 sudo mkdir /var/log/h2o sud...
- lowreal.net のHTTP2/HTTPS 化を実施 全部 HTTPS 対応にしてリダイレクトかけるようにしました。 cho45.stfuawsc.com は既に HTTPS にしてありました。こちらは nginx に letsencrypt の証明書を...
- h2o の casper を一時的に無効にする h2o の casper (cache-aware server-push) を有効にしていると、force reload したときでも push されなくなってしまって、だんだん混乱してきます。YA...
- h2o を systemd 管理下にした 徐々に daemontools 依存を外していってるが、とりあえず h2o を systemd に管理にすることにした。どうも daemontools だと annotate-backtrace-sy...
lowreal.net のHTTP2/HTTPS 化を実施
全部 HTTPS 対応にしてリダイレクトかけるようにしました。
cho45.stfuawsc.com は既に HTTPS にしてありました。こちらは nginx に letsencrypt の証明書を入れた構成だったのですが、これを機に HTTPS のフロントを h2o にして、nginx は HTTP だけを配信するようにしました。これで HTTPS は HTTP2 に対応になりました。
このサイトは割と複雑な URL の rewrite ルールをしいているので、バックエンドのアプリケーションに直接ディスパッチせず、一旦 HTTPS でも nginx を経由するようにして設定し、徐々に h2o で全リクエストを処理するように置き換えていきました。www.lowreal.net も同時に HTTPS 対応しましたがそれぞれのドメインの構成は以下の通りです
- cho45.stfuawsc.com
- h2o → static file
- h2o → backend
- lowreal.net
- h2o → static file
- h2o → backend
- www.lowreal.net
- h2o → static file (accept-language を mruby で見てる)
証明書以外にやったこと
一応 mixed content を回避したり、push してみたりしたくていろいろやりました
- はてなスターのスキーム変更
- スター画像のホスト元 (フォトライフ) のドメイン変更 (cdn-akナントカに)
- tumblr のスキーム変更
- facebook ボタン廃止
- twitter ボタンのスキーム変更
- Amazon 画像のドメイン変更 (過去に遡ってエントリ内の画像URLを変更)
- バックエンドアプリケーション (ブログシステム) へ Link: rel=preload を簡単に吐ける機能を追加
h2o での server push の確認方法
h2o は server push したコンテンツのヘッダに x-http2-push: pushed を含めてくれるので、ちゃんと push されてるか確認する一番簡単な方法はこれを見ることっぽいです。
関連エントリー
- h2o の casper を一時的に無効にする h2o の casper (cache-aware server-push) を有効にしていると、force reload したときでも push されなくなってしまって、だんだん混乱してきます。YA...
- h2o を systemd 管理下にした 徐々に daemontools 依存を外していってるが、とりあえず h2o を systemd に管理にすることにした。どうも daemontools だと annotate-backtrace-sy...
- h2o での server-push タイミングの最適化 h2o は mruby ハンドラで link ヘッダを使って push を指示すると、バックエンドへの問合せと非同期で静的ファイルを push してくれます。 もしバックエンドアプリケーションで li...
- Let's encrypt の自動更新 以下のようなスクリプトを置いて月イチの cron で更新するようにしました。証明書を更新したあと h2o を restart しています。 #!/bin/sh # sudo crontab -e # ...
- 現在の h2o.conf.yaml 今のこのサイトの h2o.conf.yaml です。HTTPS (443) のみを処理しています。HTTP (80) は nginx で受けていて、HTTPS 対応ホストに関しては nginx からは...
nginx の rewrite ルールっぽく h2o の mruby でリクエストの rewrite を行う
このサイトのHTTPS化にあたって nginx で書いていた rewrite のルールを h2o の mruby で処理するように変える必要がありました。
しかしベタで書くのも面倒なので、そこそこ機械的な置換ですむような書きかたができるようなライブラリを書いてしのぎました。
mruby.handler
paths:
"/":
proxy.reverse.url: http://localhost:5001
proxy.preserve-host: ON
mruby.handler: |
require "/srv/www/rewrite_rules.rb"
lambda do |env|
RewriteRules.rewrite(env) do
rewrite '/favicon.ico', '/images/favicon.ico', :break
rewrite '/apple-touch-icon.png', '/images/apple-touch-icon.png', :break
rewrite %r{^/2005/colors-canvas\.xhtml$}, '/2005/colors-canvas.html', :permanent
rewrite %r{^/2005/colors-canvas$}, '/2005/colors-canvas.html', :permanent
rewrite %r{^/logs/latest$}, '/', :permanent
rewrite %r{^/logs/latest.rdf$}, '/feed', :permanent
rewrite %r{^/logs/latest.atom$}, '/feed', :permanent
rewrite %r{^/latest\.rdf$}, '/feed', :permanent
rewrite %r{^/blog/index\.(rdf|atom)$}, '/feed', :permanent
rewrite %r{^/logs(/.+?)(\.(rdf|atom))$}, '/feed', :permanent
rewrite %r{^/logs(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/blog(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/photo$}, '/photo/', :permanent
rewrite %r{^/(\d\d\d\d/\d\d(/\d\d)?)$}, '/\1/', :permanent
rewrite %r{^/\d\d\d\d/$}, '/', :redirect
rewrite %r{^/view-img(/.+?)$}, '\1', :permanent
end
end h2o の path はディレクトリの指定しかできないみたいなので (自動的に末尾スラッシュがついたりする)、rewrite で同時にパス決め打ちのディスパッチも行っています。
rewrite_rules.rb
class RewriteRules
class RewriteRulesException < Exception
attr_reader :response
def initialize(response)
@response = response
end
end
attr_reader :env
attr_reader :path
def self.rewrite(env, &block)
self.new(env).run(&block)
end
def initialize(env, &block)
@env = env
@path_orig = "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
@path = @path_orig.dup
end
def run(&block)
begin
instance_eval(&block)
if @path != @path_orig
return [ 307, { 'x-reproxy-url' => path }, [ ] ]
else
return [ 399, {}, [ ] ]
end
rescue RewriteRulesException => e
return e.response
end
end
def rewrite(regexp, replace, flag=:continue)
if @path.gsub!(regexp, replace)
case flag
when :redirect
raise RewriteRulesException.new([ 302, { 'Location' => @path }, [ ] ])
when :permanent
raise RewriteRulesException.new([ 301, { 'Location' => @path }, [ ] ])
when :break
raise RewriteRulesException.new([ 307, { 'x-reproxy-url' => @path }, [ ] ])
when :continue
# nothing
else
raise "unsupported flag: #{flag}"
end
end
end
end
require 'rspec'
describe RewriteRules do
it "should treat :permanent as 302 redirect" do
env = {
'PATH_INFO' => '/logs/latest'
}
expect(RewriteRules.rewrite(env) {
rewrite %r{^/logs/latest$}, '/', :permanent
rewrite %r{^/logs(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/foobar/}, '/bazbaz/'
}).to eq( [301, {"Location"=>"/"}, []])
end
it "should treat :redirect as 301 redirect" do
env = {
'PATH_INFO' => '/logs/piyo.html'
}
expect(RewriteRules.rewrite(env) {
rewrite %r{^/logs/latest$}, '/', :permanent
rewrite %r{^/logs(/.+?)(\.(x?html|xml|txt))?$}, '\1', :redirect
rewrite %r{^/foobar/}, '/bazbaz/'
}).to eq([302, {"Location"=>"/piyo"}, []])
end
it "should treat as internal proxy by default" do
env = {
'PATH_INFO' => '/foobar/baz'
}
expect(RewriteRules.rewrite(env) {
rewrite %r{^/logs/latest$}, '/', :permanent
rewrite %r{^/logs(/.+?)(\.(x?html|xml|txt))?$}, '\1', :permanent
rewrite %r{^/foobar/}, '/bazbaz/'
}).to eq([307, {"x-reproxy-url"=>"/bazbaz/baz"}, []])
end
it "can write logic in dsl" do
env = {
'PATH_INFO' => '/foobar/baz',
'XXX' => true,
}
expect(RewriteRules.rewrite(env) {
if env['XXX']
rewrite %r{^/foobar/}, '/bazbaz/'
end
}).to eq([307, {"x-reproxy-url"=>"/bazbaz/baz"}, []])
env = {
'PATH_INFO' => '/foobar/baz',
'XXX' => false
}
expect(RewriteRules.rewrite(env) {
if env['XXX']
rewrite %r{^/foobar/}, '/bazbaz/'
end
}).to eq([399, {}, []])
end
end ところで
rewrite ルールが ruby で書けるということは、すなわち自由にテスト可能であることを意味します。Apache の RewriteRule や nginx の rewrite をテストするのはかなり面倒なので、かなり強力で嬉しい感じがします。
関連エントリー
- 現在の h2o.conf.yaml 今のこのサイトの h2o.conf.yaml です。HTTPS (443) のみを処理しています。HTTP (80) は nginx で受けていて、HTTPS 対応ホストに関しては nginx からは...
- h2o で Basic Auth Kazuho's Weblog: H2O version 1.7.0-beta1 released with enhanced mruby scripting, CGI, and much more ...
- ruby-serialport で任意のボーレートを設定するには (ただし Linux に限る) ruby serialport は、このあたりで設定できるボーレートを列挙していて、これら以外のボーレートを設定できないようです (unknown baud rate 例外)。 Linux だと io...
- KX3 でシリアルポートから SWR を読み出す KX3 と PC だけで SWR グラフにできたら便利なのになー と思っていたけど、少し前に調べたところ SWR を直接読む方法がなく、諦めていた。 しかし、KX3 Utility で Power C...
- スマートメータから瞬間消費電力を読むRubyのコード スマートメータのBルートサービスで Wi-SUN モジュールを使って瞬間消費電力を読み出す | tech - 氾濫原 にひき続き Wi-SUN モジュール ROHM BP35A1 と ECHONET ...
「みいつけた」がおもしろい
NHK Eテレの番組はそれぞれ対象年齢が設定されていて、「いないいないばぁ」は0〜2歳、「おかあさんといっしょ」は2〜4歳、「みいつけた」は4〜5歳あたりらしい。
うちの子供はまだ2歳になっていないので「みいつけた」はまだ早いことになるが、見せてみると特に嫌がらずに見ていたりする (オフロスキーは嫌いみたいだけど)。「いしゅ、いしゅ」と言うぐらいには見る。
「いないいないばぁ」と「おかあさんといっしょ」は大人が見ても面白いとはいえない感じだけど (というか無駄に元気がよくて、疲れる)、「みいつけた」は大人が見てもゆるくて面白い。
- 害になるような人物が出てこない
- 不愉快ができことが起こらない
- 現実にはありえない日常を過ごす
- 説教臭い内容ではない
あたりを考えてみると、日常系アニメと似たようなジャンルに思える。
コッシー
椅子のキャラクターでコッシーというのがいて、スタジオ内で結構自由に動くんだけど、どうやって動いているのかさっぱりわからない。謎の技術。ひっくり返るシーンとかもあって、足の裏が見えたりするけど、車輪がついていたりするようにも見えない。謎
びっくりしたのが声をあててる声優で、高橋茂雄 (サバンナ) とクレジットされている。ブラジルの皆さんじゃないほうの人・ザッカーバーグに似てるほうの人だけど、アメトークとかにしか出てないイメージだったのでびっくりした。エンディングの作詞とかもやってて余計びっくりする。全然違和感がない (喋る椅子に対して違和感もクソもない気もするけど) し聞きやすい声質だし、謎の才能。
歌の作曲が星野源だったり、この番組に限らないけどEテレの子供向け番組は凝ったキャスティングされていることがあって面白い。「おかあさんといっしょ」でもつんく作曲の歌がちょいちょいある。
関連エントリー
- みいつけた! サボさんいい 「ワンワンパッコロ!キャラともワールド」でワンワンとサボさんが共演する夢の回があって、サボさんがダンソン(バンビーノ)をやっていた。この番組、全体的に子供には難しいネタが多い。改めて見る...
- 子供用の椅子の買いかえ Stokke ストッケ ベビーチェア ハイチェア 本体 トリップトラップ 食卓 赤ちゃん 椅子 ウォールナットブラウン cho45 Stokke ★ 5.0 / 5.0 cho45 2歳になって自分で...
- 最近の子供の様子 殆ど子供の様子を書いてないが、育っている。最近の様子を書いておく 日常生活での意思疎通がかなり可能になった 例えば 「パパ、トイレ行ってもいい?」と聞くと「うん」と言ったあとトイレまでついてきてドアを...
- ASIAN KUNG-FU GENERATION New Single Re:Re: Re:Re:(初回生産限定盤)(DVD付) cho45 ASIAN KUNG-FU GENERATION ★ 5.0 / 5.0 cho45 「ASIAN KUNG-FU GENERATION New...
- 骨折20日目 今まで手首から指先までの固定だったのけど、手首あたりでシーネが切断されて手首の関節は自由となった。「つきはじめてるころだけど、これからくっつくところ。まだ強くない」とのこと 先生がおもむろに引き出しか...
LTSpice で伝送線路トランス
「伝送線路トランス」という言葉が一般的な用語かどうかよくわからないのですが、トロイダル・コア活用百科ではこのような用語になっていました。一応 transmission-line transformer で検索すると使われており、Amidon のドキュメントでも出てきますが……
それはともかく、伝送線路トランスは一見奇妙な感じがして面白いです。とりあえず LTSpice で等価回路を書いて試してみました。
位相反転回路
GND のとりかたが入力側と出力側で逆なので位相が反転します。
この回路、L1 と L2 が結合しているため、これらで1つのコモンモードチョークとして働いてアイソレーションされるために位相反転ができているのですが、なんとかく不思議な感じがします。
自分の中では「コモンモードチョーク」はノーマルモードに影響を与えないイメージなのですが、「コモンモードチョーク」があるおかげでノーマルモードの位相反転ができているのです。ぱっと見だと結線されていない GND 経由 の電流 (すなわちコモンモード) が阻止されることを強くイメージする必要があります。
ところで、結合係数を減らすとどうなるか見てみます。
これはつまりコモンモードチョークとしての機能が失われている場合です。高い結合が得られていない限り機能しなくなくなることがわかりました。
インピーダンス変換器
1:4 のインピーダンス変換器もシミュレーションしてみました。
純伝送線路トランス
伝送線路トランスを2つ使い、入力を並列、出力を直列にすることで、出力電圧を倍にできる (出力電流は半分) という回路です。単純に、それぞれの入出力がアイソレーションされていると考えると動きそうだなというイメージはできます。
が、やはり一見奇妙に見えます。
伝送線路的トランス
入力信号にトランスの出力を重合する形で出力電圧を倍にする回路です。広域が犠牲になる代わりに純伝送線路トランスよりコアの数を減らせるメリットがあります。実際の回路だとこちらのほうが良く見ます。
ぱっと見だと完全に意味不明ですが「重ねあわせる」ことを意識すると理解できるようなできないような感じがします。
通常のトランスとの違い
通常のトランスは、一旦電気エネルギーを磁気エネルギーに変換して再度電気エネルギーに変換するという動作をします。なので、高い結合係数と低いコア損失を同時に実現できなければいけません。
伝送線路トランスはコモンモードのアイソレーションによって実現されており、磁気エネルギーはメインのエネルギー伝達に使われていないので、結合係数が高ければコア損失が多少あっても問題になりません。
関連エントリー
- ✖ メモ: コモンモードは+と-が同位相なので、+と-を同時にコアに巻いてやることで強いインピーダンスを発生させることができる。ノーマルモードは+と-が逆位相なので、インピーダンスが発生しにくい。 ノーマ...
- 電圧バラン・電流バラン あんまり日本語の文書だと見ない気がするけど、英語圏由来の文書だとしばしばみるような気がする Voltage Balun, Current Balun ってなんなのだろうと思って調べたけど、つまり以下の...
- バランの役目・平衡とは何なのか いまいちイメージがしにくくて理解したとはいいきれてない部分の覚書 平衡経路は差動信号、すなわち位相が反転した信号を2線に乗せ、接地せずに伝送する。 対して不平衡経路はシングルエンド、すなわり片方を接地...
- アマチュア無線用コモンモードフィルタの特性評価 スペアナがあったらやってみたかったことの1つとしてコモンモードフィルタ(RFチョーク)の評価というのがあります。だいたいトロイダルコアを使って作っており、トロイダルコアは再現性が高いので計算通りにやれ...
- 3.5mm ジャック・グラウンドアイソレータ Aliexpress で300円ぐらい。ステレオのグラウンドアイソレータ。結構小さくていい感じ。内部的には(開けてないけど)トランスが2つ入っているはず。 広域ノイズを入力して通過した信号をオシロスコ...
10MHz バンドパスフィルタ
トロイダル・コア活用百科の応用の章にある10MHz帯用2ポールバンドパスフィルタのうち、挿入損失1dBのもので T50-6 を使ったものを作ってみました。
回路と実装
4pF が手元にないので3.9pF で代用しました。また、AWG #22 のワイヤーがなかったため、φ0.4mm で代用しています(なのでコイルのQは多少下っているはずです)
特性
実際にスペアナで同じ範囲を表示すると以下のようになりました。(多少トリマで調整した状態で、完全に追いこめてはいません)
挿入損失が 2dB になってますが、おおむね近い特性が再現できました。
ついでに 50MHz までのグラフです。綺麗に下降せずに盛りあがっています。
ここからさらに広げていっても、ほとんど減衰量は増えていませんでした (スクリーンショットを撮り忘れましたが)
関連エントリー
- 10MHz バンドパスフィルタ2 10MHz バンドパスフィルタ | tech - 氾濫原 の続きです。挿入損失 6dB バージョンの定数を変更してみました。コイルはそのままです。 定数変更 実装の関係で、書籍内の定数とすこしずれてい...
- 簡単かつ安く高精度なアンテナアナライザーを自作したい (2) 前回はある程度うまくいきそうというところまでやりました。7MHz 帯のグラフが波うっているのが気になったので詳しく原因を探して解決しました。 いくつかのバンドで測定してみると、7MHz よりも上の周波...
- DSA815-TG の 10MHz 付近の奇妙なバグとファームウェアアップグレード 測定中、10MHz 付近に急激な落ちこみが観測されることがあって気になっていました。そういうものなのかなとも思ったのですが、調べてみたら同じような問題にあたっている人がいて、まぁよく考えたらそういうも...
- 高周波用アッテネータを作ってみる 25dB で SMA 入出力のアッテネータが欲しくなったので作ってみました。アッテネータを作ってみるのは初めてです。 回路 アッテネータの計算機 を使って必要な抵抗値を求め、抵抗計算のサイトでどうやっ...
- アマチュア無線用コモンモードフィルタの特性評価 スペアナがあったらやってみたかったことの1つとしてコモンモードフィルタ(RFチョーク)の評価というのがあります。だいたいトロイダルコアを使って作っており、トロイダルコアは再現性が高いので計算通りにやれ...
10MHz バンドパスフィルタ2
10MHz バンドパスフィルタ | tech - 氾濫原 の続きです。挿入損失 6dB バージョンの定数を変更してみました。コイルはそのままです。
定数変更
実装の関係で、書籍内の定数とすこしずれています。
評価
書籍内のグラフと範囲をあわせたものです。やってて気付いたのですが、書籍のグラフは中心周波数が10MHzではないんですね。狭帯域だからかアマチュアバンドの中心?にあわせてあるのかな。手元の調整は10MHzを中心としてやっています (かなり繊細な調整が必要でした)。
帯域内は約-9dBの挿入損失になっています。
300MHz までの範囲です。100MHz ぐらいまでは -70dB ぐらいまでの減衰があります。
関連エントリー
- 10MHz バンドパスフィルタ トロイダル・コア活用百科の応用の章にある10MHz帯用2ポールバンドパスフィルタのうち、挿入損失1dBのもので T50-6 を使ったものを作ってみました。 改訂新版 定本 トロイダル・コア活用百科 —...
- メモ コモンモードフィルタの減衰 仕様通りよりも減衰しているっぽい。普通のケーブルと切り替えながらパワーメーターの値を読んだ結果: TX 設定 50W -> メーター 50W (7MHz), 50W (21MHz), 48W (21M...
- NanoVNA の測定メモ 前につくったアッテネータを測ってみる 高周波用アッテネータを作ってみる | tech - 氾濫原 NanoVNA だと 300MHz 付近にデコボコがあるようにみえますが、これはおそらく 0.5〜90...
- 10MHz GPSDO (そのうち書く) OCXO と GPS 1PPS その3 | tech - 氾濫原 というのを3年前に書いてからやる気をうしなって放置してましたが、STM32F103 bluepill と組合せて、10MHz GPSD...
- HackRF One の Sweep Mode の動作 hackrf_sweep コマンドの動作を調べたので記録しておく。このコマンドは HackRF One のファームウェアと協調して、うまく広い帯域をスイープできるように作られている。 まずいくつか定数...
アンテナアナライザーをケースに収めた
- 簡単かつ安く高精度なアンテナアナライザーを自作したい | tech - 氾濫原
- 簡単かつ安く高精度なアンテナアナライザーを自作したい (2) | tech - 氾濫原
- 自作アンテナアナライザーのBluetooth化とアプリケーション | tech - 氾濫原
あたりの続きです。
ちょっと飽きてきたというか疲れてきたので、とりあえず使えるレベルを目指すという意味でケースに収めることを優先することにしました。
発注した基板そのままでは収めることができなかったので、いろいろ試行錯誤して収めました。本来基板を設計する段階でケースまで決めてしまえればいいんですが、今回そこまで気をまわすことができませんでした。おかげでだいぶ苦労しましたがなんとか入りました。
Bluetooth モジュール用基板
Bluetooth モジュールは別途基板を自分で掘って載せるようにしました。場所がないので2階建です。
切削はそこそこ上手くいったのですが、ほとんど肉眼で確認できないのにGNDと導通があったり、実際実装してみると見えない部分で半田がショートしたりと、なかなか厳しい状態になりました。3回ぐらいモジュールの半田づけをやりなおしたのでパターンが剥れたり、ついでに勘違いからRX/TXが逆配線になっていると思ってリワークまでしたけど元々の配線であってたり、、、みたいないろんな思い出があります。
ケースの加工
CNC でやりましたが、プラスチック(ABS) の加工はものすごく苦手意識があります。アルミと違ってプラスチックは溶けるので早く動かしすぎてもダメだし遅く動かしすぎてもダメだしで「安全方向にふる」という運用が通用しないのです。
今回は以下ぐらいでやるとすくなくともエンドミルに溶けたプラスチックが固着して折れるということはなくなりました…… (2本折りました)
- φ1mm 2枚刃 エンドミル
- F500 (割と早い) Z送り50 (かなり遅い)
- 回転数 50% 約5000rpm
- S500 指定だが、最大1000を最大の電圧として500だけ電圧をかけるという意味で、500は回転数ではない (最大の50%の回転)
タコメータをつけてないので回転数が正確にわかってません。
インターフェイス
見ての通りですがインターフェイス的には
- 電源スイッチ
- LED (Bluetooth の接続状況: 接続待ちは点滅・接続済みは点灯)
- BNC コネクタ
しかありません。これは最初からこうするつもりで作っていて、Bluetooth 経由で接続したスマートフォンから全ての操作を行うという設計です。
というのも、アナライザを作るなら、まず絶対に Bluetooth などで無線化したいという思いがありました。なぜかといえば、実際にフィールドでアンテナの調整を行う場合、給電点と調整点というのは必ずしも一致しておらず、既存のアンテナアナライザーだと給電点と調整点をいったりきたりする必要があって面倒だからです。例えば7MHz帯の半波長逆Vダイポールをフィールドで一時的に立てようと思うと、給電点と調整点では10mぐらいの距離があってしんどいのです。
今後
これでとりあえず使えるぐらいにはなりました。しかし、かなり問題があります。
- Android 側のアプリケーションの完成度がいまいちなのをなんとかする
- ソフトウェアだけなのでおいおい
- インピーダンスのグラフが波うつ
- どっかで反射の影響が起きていると思うけどどこかわかってない
- RFアンプの設計からやりなおす
- というか面倒なのでMMIC使うとか
- 低消費電力化
- RFアンプに常時電源供給してしまっているのをやめる
- RFアンプの再設計
- AD9851 と Bluetooth デバイスの消費電力がデカいのでできることは限られる
- ケースに組みこんだら計測にノイズが乗るようになった
- NiMH 2本を電源にしたいと拘ったため、DC/DC で 5V まで昇圧しているが間違いなくノイズ源になっている
- Bluetooth モジュールとADC部が近い
- もっと小さく作りたい
- MCU が無駄にでかい
単三電池2本の電源内蔵するのも今回なぜかこだわっていたのですが、どうせDC/DCで昇圧するならモバイルバッテリ使えるようにして、電池は内蔵しないほうがコンパクトかつ総合的には荷物が減って良さそうです。
関連エントリー
- 自作アンテナアナライザーのBluetooth化とアプリケーション 簡単かつ安く高精度なアンテナアナライザーを自作したい | tech - 氾濫原 簡単かつ安く高精度なアンテナアナライザーを自作したい (2) | tech - 氾濫原 あたりの続きです。 シリアル接続...
- スペアナとリターンロスブリッジを使ってSWRを測ってみる リターンロスブリッジを買ってみたので、手元にあるいろんなものを測ってみました。 測定方法 普通のリターンロスブリッジなので、DUT をオープンしてノーマライズ、DUT に測定対象を接続してリターンロス...
- 免許がきた 8月17日 (日) に電子申請 (11日ほど進捗なし、一度フォームから問合せた) 8月28日 (水) ステータスが審査中に 8月29日 (木) 手数料払込の案内、即日払込み。前もって書いておいたSAS...
- 簡単かつ安く高精度なアンテナアナライザーを自作したい いろいろ回路の説明を見たりしていたのは自分で作ってみたかったからです。既製品を1つ持っていますが、海外製なので壊れたときに不安です。自分で作れれば既製品に頼る必要がひとまずなくなるので安心できますし、...
- Ruby の serialport gem で Bluetooth SPP を使おうとすると Errno::EBUSY Ruby の serialport gemで Bluetooth SPP を使おうとすると Errno::EBUSY がでてうまく通信できず、なんでだろう、となりました。接続先の Bluetooth ...
cordova run android --device でエラー
:processDebugResources FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':processDebugResources'. > com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/cho45/Library/Android/sdk/build-tools/23.0.1/aapt'' finished with non-zero exit value 1
こんなエラーで死んでしまいました。gradle 経由で実行されてるんですが、gradle へのコマンドラインオプションの渡しかたがわからず……
cordova clean したり rm -rf platforms/android しても解決しなかったのですが、Dropbox に入れておいたせいで、ソースツリー内に「www/src/app (xxxx 競合コピー 2016-03-30).js」のようなファイル(特に心あたりなし)ができており、これを削除したら解決しました。稀な例だと思いますが…
関連エントリー
- Spring MVC で @Async と @RequestScope を共存させるには? @Async と @RequestScope を同時につかうとどうなるか @RequestScope、これは @Scope(value = "request", proxyMode = ScopedP...
- capacitor で Android 向けに minifyEnabled true Android では、アプリのサイズをできるだけ減らしたりするために、リリース前にアプリ全体のコードの最適化 (いわゆるツリーシェイキング) が推奨されている。動作としては、実行されるコードを解析で割...
- WSL2 で USB (usbipd-win) https://github.com/dorssel/usbipd-win WSL2 内ではホストの USB デバイスを使うことができないという大きな欠点がある。WSL2 のベースとなる Hyper-...
- https 通信が不可能な原因が時刻ずれ 手元の NanoPi NEO2 が、証明書エラーでどうしても https 通信が不可能に。 Ubuntu 16.04 なのでそれほど古いOSというわけではない。証明書関係だろうと思いいろいろやってみた...
- Raspberry Pi から HDMI-CEC コントロール サイネージ HDMI CEC 連携 カレンダーを表示するおうちサイネージ というのを作っていたがモニタの置き場がなくなってしまったので、テレビ画面に映すことにしてみた。 Google TV と Swi...
体調不良
朝に悪心で眼が覚め、すこしすると連続した水下痢に。断続的に下痢が出続ける。
悪心もあるので寝ていようとしたが、寝ると夢の中でも下痢をしており、ケツから漏れるという夢を見て「ガタッ!!」と起きること数回、「夢は見るものではなく実現するもの」と言わんばかりに夢じゃなくなったので履いていたパンツは捨てて新しいのし、ズボンは漂白に。
一通り落ちついてきたので一旦会社に行ってしょぼいタスクをやって、やっぱキツいので帰宅して寝ていたが、不用意に寝ると漏れる夢を見るので落ちつかず。
最近子どもが胃腸炎だったので伝染ってきたようだ。妻も胃腸炎で死んでおり、家庭が崩壊している。なお子どもはもう割と元気。
パンツ捨てるときはこれに入れた。ほんとこの袋は死ぬほど便利だ
関連エントリー
- 今年最悪の体調不良 ガチ嘔吐するまで体調が悪化した。なんか悪いもの食べたのかもしれないけどよくわからない。 土曜日を0日として -3〜-1日 下痢 0日 午前中 少し悪寒 12時〜 昼食後 だるさと吐き気 5時〜 さらに...
- こ、こいつは臭ェ…… 幼児のおむつ替え(うんこ)時に最高に便利なライフチェンジンググッズ 離乳食がはじまると子どものうんこが超絶臭くなり、臭い耐性が著しく低い自分はうんこが出てることがわかると妻を呼ぶみたいな運用をしていた。当然これは良くないが…… そうはいっても臭すぎてケツが綺麗に拭けた...
- 我が家のコロナ禍 学校でクラス内感染の連絡がきたその日に子ども(8歳でワクチン2回目から4ヶ月経過)が頭痛を訴え、夕食も食べずずっとベッドで寝るという状態に。と思いきや翌日は症状がなく、受診すべきか悩むぐらい元気という...
- 年末だし子供関係で買ったものを一括でレビューするぞ!!! 驚異の防臭袋 BOS(ボス)Sサイズ大容量200枚入り 赤ちゃん用 おむつ 処理袋 (袋カラー:ピンク) cho45 BOS ★ 5.0 / 5.0 cho45 みんな知らないと思うけど、うんこは臭い...
- ボタン電池で動く小型・低消費電力 AVR エレキー (50円 ワンチップマイコン ATTiny13A) とりあえず完成なので、今まで書いたやつのまとめで整理。 要求 外に持ちだせるように小型で電池駆動できること 電池交換をあまり気にしなくてもいいこと 実用的であること 仕様 短点・長点それぞれ1点のメモ...



















