write ahead log

ロールフォワード用

雑に使えるHTTPサーバー作った

なんか最近色々面倒だし、作った。

こんなの使わなくても、もっといいのがある気もする。

httpbinとかいいかなと思ったけど、微妙に欲しいのと違った。

github.com

なんで作ろうと思ったんだっけ?となったので、なんか色々面倒だった事を書いておく。

(その前に)面倒な状況0

そもそもこういうのは入れるのが面倒なのでcurlでダウンロード&解凍で使えるようにした。

# windows(CMD。Powershellわからない)
curl -OL https://github.com/twinbird/hits/releases/download/v0.0.1/hits_windows_x86_64.zip
# 右クリックからzipを解凍
./hits

# linux
curl -OL https://github.com/twinbird/hits/releases/download/v0.0.1/hits_linux_x86_64.tar.gz
tar xfvz hits_linux_x86_64.tar.gz
./hits

# macはしらんけどたぶんlinuxと同じじゃないですかね。。。

Goはバイナリ1つなんで、ダウンロードファイル消せば環境汚さなくていい。

面倒な状況1

「よそ様のREST API叩くコード書いたのになんか動かん」みたいなのがあって、私はプリントデバッグしかできない愚か者なのでとにかく中身を見たかった。

とりあえず叩く時にはcurlでこんなのしたり雑にできるのに、雑に受けるってのが意外となくて困った。

curl -X POST \
    -d "key=your key" \
    -d "secret=your secret" \
    -d "param="parameter" \
    http://nice-service/nice-api/v1/post

hitsを使うと

以下で起動したら標準出力にアクセスしてきた情報を表示するようにした。

./hits

Time:
        2021/11/16 23:59:02
URL:
        /nice-api/v1/post
Method:
        POST
Protocol:
        HTTP/1.1
Header:
        Content-Length:47
        Content-Type:application/x-www-form-urlencoded
        User-Agent:curl/7.68.0
        Accept:*/*
Body:
        key=your key&secret=your secret&param=parameter
Parameters:
        key:your key
        secret:your secret
        param:parameter

面倒な状況2

「別会社がシステム作ってくれるはずだけど、そこまだ出来てないからとりあえず適当にサーバー立てて、適当なスクリプトでログ取って」みたいなのがめんどい。

hitsを使うと

別に1と同じなんだけど、ログファイルを指定できるようにした。

レスポンス返せとか、500返せとかがありがちなんで一応つけた。

./hits -o log.txt -r "It Works!" -s 200

面倒な状況3

「お客さんにHTMLのデザインモックzipで送って見てもらいたいんだけど、サーバーないしどうしよう」みたいなのがめんどい。

hitsを使うと

ディレクトリ指定してサーブする機能を付けた。今度からbat書いて送りつけようかなと思う。

./hits -d doc_root

面倒な状況4

とりあえず適当なJSON返すサーバーがほしい。

hitsを使うと

レスポンスヘッダー指定するオプションも加えたけど、JSON返すこと多すぎなのでオプションにした。

返す内容も変えたいので、標準入力とかファイル指定もできるようにもした。

cat response.json | ./hits -j

その他

どうせいつか使うだろうとベーシック認証とかルーティング定義みたいなのも入れた。

使うのか?

雑感

Goで書くとどこでも実行ファイル1つをコピーしたり削除したりでいいので使い勝手がいいなと思った。

「開発環境のサーバー使え」って思ったけど、「それが出来たら苦労しねー」と思った。

メンテめんどいから標準ライブラリだけで作るつもりだったのに、id:mattn氏のライブラリからだけは逃れられなかった。怖い。

書いてて気づいたけど、git bash上での標準入力周りの挙動修正と、TLS対応が欲しいと思って入れてなかった。めんどい。必要になったらやろう。だれかやってくれ。

最近めんどうばっか言ってるな俺。

ssh先からローカルのクリップボードへコピーしたい

ググるとOSC52というものが出てきた。

OSC52って何ぞや

クリップボードを操作するエスケープシーケンスらしい。

こんな丁寧な解説があったので読むとこんな感じか。

文字 意味
\033 エスケープシーケンスの開始
52 OSC52グループのエスケープシーケンスだよ
; 区切り
c クリップボードへコピーしてくれ
; 区切り
文字列 クリップボードへコピーする文字をBASE64にしたもの
\a エスケープシーケンスの終わり

試しにssh先でこれをやってみるとローカルのクリップボードへ"HELLO, world"が入った。すげぇ。
(後に書くようにターミナルエミュレータへ設定が必要)

printf "\033]52;c;%s\a" $(echo "HELLO, world" | base64)

もっと簡単にやりたい

なんかスクリプト書くかと思ったら、なんと良いのがchromiumリポジトリ内にあった。 https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc/osc52.sh

githubのミラーはこちら https://raw.githubusercontent.com/libapps/libapps-mirror/main/hterm/etc/osc52.sh

なのでこういう感じで楽に設定できる

 curl -L https://raw.githubusercontent.com/libapps/libapps-mirror/main/hterm/etc/osc52.sh -o osc52.sh
 chmod +x osc52.sh
 sudo mv osc52.sh /usr/local/bin

するとこんな感じにできる

 echo 'HELLO' | osc52.sh # これでクリップボードへコピーされる

OSC52を許可するのはセキュリティリスクの懸念で、デフォルトでは無効になっている端末エミュレータが多いらしい。
(リモート先に悪意があるとクリップボードを簡単にいじれちゃうから?具体的な攻撃方法とかは調べたけどわからん。一応気を付けたほうがいいのかな)

git bash(mintty)で使うには設定が必要。

.minttyrcに以下を書く。

AllowSetSelection=yes

windows terminalだと設定不要っぽい。

tmux実行中でも動いた。screenもコード読む限り通りそう。というかコードがきれい。

余談だけど

ここを見るとvimemacsスクリプトもある。

https://chromium.googlesource.com/apps/libapps/+/master/hterm/etc

redoc-cliを使ってopenapi(swagger)を書く

肌に合ったツールがわからなくて困ってたけど、良いのがわかったのでメモしとく。

準備する

nodeはインストールされているとして。

とりあえずプロジェクト用のディレクトリを用意してredoc-cliをインストールする。

mkdir api-project
cd api-project
npm install redoc-cli

プレビューしながら書く

それっぽくopenapiのyamlを書く。

vi api.yml

プレビューするためにサーバーを起動する。

npx redoc-cli serve api.yml --watch

これで

localhost:8080

へのアクセスでプレビューしながら編集できる。

HTMLとして出力する

単一の依存なしHTMLファイルとして出力できる。便利。

npx redoc-cli bundle api.yml

ブラウザで動くアウトラインエディタを作った

Vue.jsをもうちょっと触っといた方がいいかな, ぐらいの軽い気持ちで作っていたけどNetlifyだと無料で配信できるし公開しておく.

bonsai-outliner.netlify.app

どう見たってWorkFlowyとかDynalistを使う方が良いのだが, ショートカットをUnixキーバインドっぽく仕上げたら思いの外便利になってしまった.

Google Driveへの保存機能も作っていたが, APIの利用申請にYou Tube動画の登録が必要になって面倒になってやめた. (利用するAPIを絞れば大丈夫そうだけど, ふつーのテキストファイルで保存したいのよなぁ.あとDrive API調べるの面倒...)

自分が使う分にはテキストファイルへのエクスポートとブラウザ内への保存だけで十分だし, 案外このまましばらく使い続けるかもしれない.

余談だけど普段買わないWEB+DB PRESSのVol.120にあったVue.jsの入門記事が大変役に立った.

自作OS×自作ブラウザの記事の方が興味があって買ったのに、結局読み込んだのはVueの記事になってしまった.

私のように大して難しい仕事をしない人はこの記事とGoogleだけでも結構使えるようになる気がする.おすすめ.

gihyo.jp

Vagrantのubuntu(ubuntu/bionic64)で12ステップで作る組込みOS自作入門の環境を作った時のメモ

h8writeとターミナルアプリは諦めてホストOSのものを使った. (Windowsでteratermとkz_h8write)

VirtualBoxからUSBやシリアルポートを使う方法もあるようなのだけど, どうもうまくいかない.

USB Type-Cしかないマシンなのでその影響が出ている気がしないこともない.

クロスコンパイル用のbinutilsとgccは著者のサイトから取得してきた.

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install flex

# binutils
$ curl -OL http://kozos.jp/books/makeos/binutils-2.19.1.tar.gz
$ tar xfvz binutils-2.19.1.tar.gz
$ cd binutils-2.19.1/
$ ./configure --target=h8300-elf --disable-nls --disable-werror
$ make
$ sudo make install

# gcc
$ curl -OL http://kozos.jp/books/makeos/gcc-3.4.6.tar.gz
$ tar xfvz gcc-3.4.6.tar.gz
$ cd gcc-3.4.6/
$ vi gcc/collect2.c
# 書籍記載の内容通り変更
$ wget http://kozos.jp/books/makeos/patch-gcc-3.4.6-x64-h8300.txt
$ patch -p0 < patch-gcc-3.4.6-x64-h8300.txt
$ mkdir build && cd build
$ ../configure --target=h8300-elf --disable-nls --disable-threads --disable-shared --enable-languages=c --disable-werror
$ make
$ sudo make install

makeしたmotファイルをホスト側のh8writeで書き込めばとりあえずstep1はクリアできる.

VM便利だけど, いちいち面倒だしubuntuマシンが欲しくなる.

Laravel Duskで要素数を数えたり現れる順序をテストしたかった

直接的なアサーションがなかったから作った. TestCaseでuseして使うtraitにしてみた.

たぶんMacroを用意するのが正当なアプローチだと思うんだけど, 調べるの面倒で雑に書いてしまった.

<?php

namespace Tests;

use Facebook\WebDriver\WebDriverBy;

trait MyDuskAssertions
{
    /**
     * $selector要素が$count個あるかをassertionする
     * 
     * Usage:
     *   $this->myAssertElementsCountIs($browser, 'tbody>tr', 1);
     */
    public function myAssertElementsCountIs($browser, $selector, $count)
    {
        $elements = $browser->driver->findElements(WebDriverBy::cssSelector($selector));
        $this->assertCount($count, $elements);
    }

    /**
     * $textsが$selector内で順番に現れるかassertionする
     *
     * Usage:
     *   $this->myAssertSeeInOrder($browser, 'tbody td', ['No.1', 'No.2', 'No.3']);
     */
    public function myAssertSeeInOrder($browser, $selector, $texts)
    {
        $targets = $texts;
        $elements = $browser->driver->findElements(WebDriverBy::cssSelector($selector));
        $msg_texts = implode(',', $texts);

        foreach ($elements as $e) {
            $expect = reset($targets);

            if ($e->getText() == $expect || $e->getAttribute('value') == $expect) {
                array_shift($targets);
            }
        }
        $this->assertEmpty($targets, "'$msg_texts' were not see in order in '$selector'.");
    }
}