Note

3年後の自分のために書いています

証明書まわり学習メモ

自分でも理解が超曖昧なのでまとめる。随時更新していく。

公開鍵証明書

デジタル証明書や単に証明書とも呼ばれる

公開鍵証明書 - Wikipedia

CSR(証明書署名要求)

証明書署名要求 - Wikipedia

秘密鍵

公開鍵基盤(PKI

公開鍵基盤 - Wikipedia

OpenSSL

OpenSSL - Wikipedia

RSA暗号

RSA暗号 - Wikipedia

デジタル署名を実現するための暗号方式。

超雑な説明。

  • めっちゃ大きい素数(p, q)同士の掛け算をしてその答えを x とした時に
  • x を公開鍵、p, q を秘密鍵とするやつ

デジタル署名

デジタル署名 - Wikipedia

SSL/TLS

Transport Layer Security - Wikipedia

SSL/TLS 証明書

サーバー証明書/中間CA証明書/ルート証明書の違いとは? | さくらのSSL

  • ルート証明書
  • 中間証明書
    • サーバが持ってる
    • ルート証明書サーバ証明書に署名すると、サーバ証明書を失効させるコストが高くなっちゃうので間に挟むやつ
    • ブラウザ側がよしなに中間証明書をダウンロードして正常に動いてしまう場合もあるため、サーバへの設置漏れに気づけないこともある
  • サーバ証明書
    • サーバが持ってる
    • ドメインを保証するやつで、大体「SSL 証明書購入しといて」と言われたらこれのこと

Redis での Rate limit 実装

〇〇 req/sec という rate limit を実装する例。 どちらも Fixed window counters を前提に説明する。

結論

  • Rate limit 機能はカウンター(INCR)の要不要によって、最適な実装が変わる
  • カウンターが必要な場合は timestamp 入り key を window に、不要な場合は ttl を window にするのが良さそう

カウンターが必要な場合

5req/sec、10req/sec などに制限するような場合 Redis の公式ドキュメントに記載されていた rate limit 実装を 丸パクり 参考にするのが良さそう

See. https://redis.io/commands/INCR#pattern-rate-limiter-1

# 公式ドキュメントの擬似コード
FUNCTION LIMIT_API_CALL(ip)
ts = CURRENT_UNIX_TIME()
keyname = ip+":"+ts
MULTI
    INCR(keyname)
    EXPIRE(keyname,10)
EXEC
current = RESPONSE_OF_INCR_WITHIN_MULTI
IF current > 10 THEN
    ERROR "too many requests per second"
ELSE
    PERFORM_API_CALL()
END

処理の流れ

  • key に何らかの識別子(例では IP アドレス) & 秒ごと(unixtime)の timestamp 付与
  • INCR と EXPIRE を atomic に実行
  • INCR の戻り値の値で rate limit を超えているか判定し、API コールするかどうか決める

感想 & メモ

  • key に timestamp が入ってるので実行秒ごとの rate limit counter が生成されて、不要になったら expire で設定した秒数後に消えるイメージ
  • INCR の「key が存在しない場合は指定された key に 0 をセットしてから increment する」という挙動がミソ
  • ちなみに 〇〇req/min の場合の実装例は https://redis.com/redis-best-practices/basic-rate-limiting/ に載ってる
  • 後述の通り、カウンターが必要なケースで ttl を window に使ってしまうとレースコンディションが発生しうる、かつそれを回避しようとすると実装が複雑になるので、現時点ではこの実装が最適解と考えている

単一のカウンターで ttl を window に使うのはダメなの?

何らかの理由で INCR 後の EXPIRE のセットが失敗すると rate limit が機能しなくなる。 Redis ドキュメントにもレースコンディションが発生しうる、かつこれを回避するには複雑な実装が必要との記載あり。

See. https://redis.io/commands/INCR#pattern-rate-limiter-2

カウンターが不要な場合

1req/sec に制限するような場合

処理の流れ

  • SETEX で ttl を 1 にして key にしてセット
  • key の有無によって API コールするかどうか決める

感想 & メモ

  • SETEX は atomic な処理でこちらは確実に ttl のセットが保証される
  • カウントが不要な場合はこのやり方がシンプルで良い、やはり INCR を混ぜると一気に難しくなるのだと思う

20230717更新

いや、この場合もマルチスレッド環境にて同じタイミングで GET が走ると複数回 API リクエスト実行されるから競合状態は起きうる。(典型的な check-then-act 処理)

参考

diesel_cli のインストールで失敗する場合の対処法

$ cargo install diesel_cli --no-default-features --features postgres した時に以下のようなエラーが出る場合の対処方法を記す。

$ cargo install diesel_cli --no-default-features --features postgres
   ...
   Compiling diesel_cli v1.4.1
error: linking with `cc` failed: exit status: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "/var/folders/y_/4r9vf_jn4qx6wd44z61hd7bm0000gp/T/cargo-installc0nGsu/release/deps/diesel-c3215a2deafd6029.diesel.47e90c54-cgu.0.rcgu.o" "/var/folders/y_/4r9vf_jn4qx6wd44z61hd7bm0000gp/T/cargo-installc0nGsu/release/deps/diesel-c…nodefaultlibs"...
  = note: ld: library not found for -lpq
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: failed to compile `diesel_cli v1.4.1`, intermediate artifacts can be found at `/var/folders/y_/4r9vf_jn4qx6wd44z61hd7bm0000gp/T/cargo-installc0nGsu`

Caused by:
  could not compile `diesel_cli` due to previous error

結論

以下のどちらかで解決する。

  • postgresql をインストールする
  • libpq をインストールして PATH 通す
$ brew install postgresql
$ cargo install diesel_cli --no-default-features --features postgres
# or
$ brew install libpq
$ PATH="/usr/local/opt/libpq/bin:$PATH" cargo install diesel_cli --no-default-features --features postgres

公式ドキュメント(のドラフト)的には postgresql をインストールするよう書いてあるので、普通にそっちで良さそう。

See. https://github.com/diesel-rs/diesel/blob/v1.4.8/guide_drafts/backend_installation.md#mac-osx

説明

  • --no-default-features --features postgresdiesel のバックエンド(DB)を postgres に限定するオプション、デフォルトでは dieselmysql, sqlite, postgres 全てのクライアントライブラリのインストールを要求する
  • libpq は keg-only(デフォルトで PATH が通らない)なパッケージなので、明示的にパス指定してやらないと動作しない
    • 以下、$ brew install libpq した時に表示されるメッセージ
      • libpq is keg-only, which means it was not symlinked into /usr/local, because conflicts with postgres formula.

参考

型システム入門 プログラミング言語と型の理論(TAPL)読書メモ

See. 型システム入門 プログラミング言語と型の理論 | Amazon

メモ

知りたかったこと

型システムのメリットを分かりやすく

TAPL 1.2 に書いてあったので自分なりに要約する。

  • エラーの検出
    • 静的型検査の最も分かりやすい恩恵、プログラミングのエラーを実行前に検出できる
    • 型検査時の方がエラー箇所を正確に特定できることが多い
  • 抽象化
    • モジュールのインターフェース(これ自身「モジュールの型」とみなせる)と実装を切り離して設計・議論することで、インターフェースをより抽象的に捉えることができる
  • ドキュメント化
    • 型宣言によりコードを理解しやすくなる、またこのドキュメントは静的型解析によって常に検査されるので古くなることもない
  • 言語の安全性
    • 静的型の安全性とは違う話らしい、、あまり理解できなかった
  • 効率性

👆 に加えて、今なら IDE による補完などもメリットに入ると思う

Also see. 私と型システムとポエム - The curse of λ

代数的データ型とは

TAPL 読む前の知識

TAPL 読んだあと

  • ...

部分型付けについて

  • 構造的部分型とは A: { a: number } :> B: { a: number, b: string } の A, B のように、親の型の構造が子のそれを含有する時、部分型であるとみなす型システム
  • 名前的部分型とは B extends A のような宣言があった場合のみ部分型であるとみなす型システム
  • A が親(上位型)で B が子(部分型)、子の方が親より多くのフィールドを持つ(!)
  • TAPL 15.2 にフィールドの数が多い方がより小さい型(部分型 = 子の型)であるのは意外かもしれない。って書いてて自分がずっと引っかかってたところだったので最高!となった。 曰く、「フィールドが多い型の方がより要求の厳しい(より情報量のある)仕様を構成し、値のより小さな集合を形成することになるため」
  • 共変と反変についても15.2に書いてある

iOS アプリ開発のメモ

Xcode

  • 2021/08 現在 App Store からインストールできる安定版の最新は v12.5.1、Apple のサイトからならベータ版の Xcode 13 もインストール可能
  • Xcode 13 から vim mode が使える
  • フォーマッタがない、一応インデントの揃えだけ ctrl+i でできる
  • プロジェクト作るとプロダクト名(= プロジェクトルートのディレクトリ名)がそのままエントリーポイントのクラス名になるので、パスカルケースで書かないといけない
  • playground でピュアな Swift コードの実行もできる

Swift

参考

無料にこだわる個人開発アプリ・システム構成

[2024/02/26 Update]

Vercel もDB 提供するようになったし、Planetscale や Supabase も出てきてます。この記事の内容は古いので鵜呑みにしないでください。

[2022/08/26 Update]

Heroku 有料になりましたね、、無念。


チラシの裏的な記事です。やっぱりなるべく無料にこだわりたい。

Next.js + Vercel + DynamoDB

  • Vercel と DynamoDB の間に API Gateway と Lambda 挟むパターンだと API Gateway で課金される
  • 実装例 https://github.com/leerob/nextjs-aws-dynamodb
  • Vercel は個人的かつ非営利目的なら無料プラン利用可能
  • Vercel の Serverless Functions はめちゃ便利
    • 現状だと Node.js (TypeScript), Go, Ruby, Python が使えるけど、フロントエンドとの型定義の共有とかサポートの優先順位考えると素直に TypeScript 使っとくのが良さそう

Node.js or Rails アプリ + Heroku + Heroku Postgres + Heroku Redis + その他アドオン

  • Heroku やっぱ強い
  • 他言語のアプリも載せられるけど(自分の使える言語の中だと)Node と Ruby のサポートがいい
  • 無料の場合スリープモードへの対策が必要
  • Next.js は単なる Node アプリなので Heroku にデプロイすることもできる(パフォーマンス的な意味での Next.js の良さは削がれる)

Create React App or Next.js (Static HTML Export) + Firebase Hosting + Firebase Authentication + Firestore + Cloud Storage

  • Firebase に全部のっかるパターン、クライアントアプリは Firebase Hosting でホスティングしなくてもいいけど
  • Firebase Authentication や Firestore などは単体でも便利なのでそこだけ切り出して Vercel(やその他サーバ)と繋げるのもあり
  • Cloud Functions 使えば外部 API も叩けるけど Blaze プラン必要

Dockerfile + Cloud Run

GAE (Google App Engine)

  • Google だし Go と相性いいのかしら(よくわかってない)

番外編「静的 Web サイトをホスティングするなら」

[2024/02/26 Update]

今なら Cloudflare Pages かなぁ


  • 現状だと Netlify が一番好き
  • GitHub Pages 好きだったけど Netlify と比べると反映遅いし、Firebase Hosting や Vercel を静的サイトのホスティングに使うのは何かオーバースペック感ある

感想

  • やはり個人開発には Vercel, Heroku, Firebase 辺りが強い味方
  • フロントエンドは Create React App と Next.js で迷ったら Next.js 使っとけばいいかな(静的サイトの場合でも)、と思ったけどまだ迷い中
  • とりあえず無料で個人開発するには無料で使えるサーバと DB(またはその代替となるもの)を見つけるのが鍵っぽい
    • 要件的には外部 API を叩けることと任意のデータを永続化できること、かな

参考

API や DB のスキーマからコードを自動生成する系のツールを触ってみた

APIスキーマからコード生成する系

OpenAPI Generator

チュートリアルなかったので拾ってきた OpenAPI の定義ファイルから typescript-fetch なるジェネレータでコード吐くところまでやった。

メモ
参考

GraphQL Code Generator

チュートリアルなかったので適当な graphql スキーマからクライアントの生成(typescript-operations, typescript-graphql-request)とリゾルバの型定義の生成(typescript-resolvers)するところまでやった。

メモ
  • 主に TypeScript 用、GraphQL のスキーマ(とクエリ)から API クライアント(React 用とかもある)を生成したり、サーバ側のリゾルバの型定義を生成したりできる
  • 基本の @graphql-codegen/typescript だけだと最低限の型定義のみで、プラグインを使うことでクライアントやリゾルバの型定義を生成できる
  • ts 以外にも java のリゾルバとかも吐けるっぽいけど、基本は ts 向け
参考

gqlgen

Building GraphQL servers in golang — gqlgen やった。

メモ
  • GraphQL のスキーマからサーバ側のコードを生成する Go のライブラリ
  • チュートリアルではスキーマからコード生成 -> resolver 実装 -> モデルのコード変更(自動生成された graph/model/models_gen.go とは別に graph/model/xx.go 的なファイル作る、struct の名前被ってても generate コマンド打てば勝手に上書きしてくれる) -> generate コマンドで未実装の resolver 生成 -> スキーマを満たす resolver 実装って感じ
    • 👆 ではコード変更がモデルから始まってるけど、実運用で変更を加える際には最初にスキーマ変更やってからモデルの変更になるのかな
  • メルペイの人が gplgen で todo アプリの API サーバ作る動画があって、便利さが分かりやすい
参考

gRPC

Quick start | Go | gRPC やった。

メモ
  • gRPC っていうかスキーマファーストやコードの自動生成の文脈で大事なのは Protocol Buffers の方か(もうちょい調べる)
  • あと、gRPC はブラウザで動かないので Web のフロントエンド ⇄ バックエンド間の通信には使えない(サーバ間通信に使う想定)
    • 👆 を解決するために grpc-web なるものもあるが、実体は xhr リクエストなので動かすには gRPC Web Proxy なるプロキシサーバが必要(フロントエンドでも Protocol Buffers の型定義を使い回せるのが利点)
参考

DB or モデルのスキーマからコード生成する系

Prisma

Quickstart: Getting started with TypeScript & SQLite | Prisma Docs やった。

メモ
  • モデルの定義を Prisma schema で書くと型安全な DB クライアントを自動生成してくれる ORM(今は TS/JS 用だけど、Go もサポートされるかも)
    • Prisma schema が読み書きしやすくて良い、自動生成してくれるコードも過不足なく良い感じ
  • mizchi 氏の「お節介ではないクエリビルダ」っていう表現がしっくりきた
  • Prisma1 の頃は GraphQL 優先のツールだったっぽいけど、今の Prisma2 では GraphQL あんま関係なくなってる
参考

Hasura

コース紹介 | Hasura GraphQLチュートリアル を途中までやった。

メモ
参考

今回やらなかったこと

調べていく中で見つけたやつ。