$30 off During Our Annual Pro Sale. View Details »

awkでつくってわかるWebアプリケーション / Web Application Implem...

yammerjp
February 10, 2024

awkでつくってわかるWebアプリケーション / Web Application Implementation in awk

YAPC::Hiroshima 2024での、awkによるWebアプリケーションの実装方法について紹介した発表の資料です。

元となった実装は https://github.com/yammerjp/awkblog にあります。
デモアプリケーションは https://awkblog.net にあります。

yammerjp

February 10, 2024
Tweet

More Decks by yammerjp

Other Decks in Programming

Transcript

  1. GMOペパボ株式会社 EC事業部 ECグループ プロダクトチーム エンジニアリングリード 2021年 新卒入社 2 自己紹介 中山 慶祐

    Nakayama Keisuke あだ名: やんまー (yammer) Webアプリケーションエンジニア 趣味: 🤿, dotfiles盆栽, awk :   @yammerjp https://twitter.com/yammerjp https://github.com/yammerjp
  2. 3 アジェンダ 1. 自己紹介 2. awkとは? 3. HTTPサーバ 1. レスポンス

    2. リクエストヘッダ 3. リクエストボディ 4. その他 5. デモ
  3. 4 アジェンダ 1. 自己紹介 2. awkとは? 3. HTTPサーバ 1. レスポンス

    2. リクエストヘッダ 3. リクエストボディ 4. その他 5. デモ プログラミング言語awkで ブログシステムを作った話 https://github.com/yammerjp/awkblog
  4. 1977 awk 2024 YAPC::Hiroshima 2010 Rust 2009 Go 1995 PHP,

    Ruby, JavaScript 1987 Perl 1972 C 6 awkとは 1977〜
  5. 12 awkとは 複数の処理系 awk (One True Awk) gawk (GNU Awk)

    nawk mawk … TCP/IPなどの 様々な拡張
  6. 29 HTTPレスポンス HTTP/1.1 200 OK Content-Length: 61 Content-Type: text/html; charset=utf-8

    <!DOCTYPE html> <html> <body> 投稿しました </body> </html>
  7. 30 HTTPレスポンス HTTP/1.1 200 OK Content-Length: 61 Content-Type: text/html; charset=utf-8

    <!DOCTYPE html> <html> <body> 投稿しました </body> </html> このようなテキストを 出力すればいい
  8. 35 HTTPレスポンス - responseを出力する - 出力先はTCPのポート 8080に接続してきた クライアント |& …

    双方向パイプ 入出力先を指定 できる記法 https://gist.github.com/yammerjp/7ca4aedf5e15cbdb6c7f02401cfacfe2 ↑ファイルに保存して実行できる $ gawk -f main.awk _
  9. 43 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21
  10. 44 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 このようなテキストを 読み込めばいい
  11. 45 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ
  12. 46 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ まずはヘッダを 読み込むことを考える
  13. 48 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは
  14. 49 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 行 行 行 行 行
  15. 50 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行
  16. 51 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ 行ごとに 行 行 行 行 行
  17. 52 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ 行ごとに 行 行 行 行 行 RS = ”\r\n” 入力の区切り文字 (一回の入力で どこまで読むかを宣言)
  18. 53 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行
  19. 54 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行 空行ならば (1行のByte数) = 0
  20. 55 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行 空行でないならば (1行のByte数) > 0
  21. 56 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行 while(INET |& getline && length($0)) {
  22. 57 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ リクエストヘッダは 行ごとに空行まで読めばいい 空行 while(INET |& getline && length($0)) { 1回の入力で 読んだByte数
  23. 63 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ
  24. 64 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ つぎはボディを 読み込むことを考える
  25. 65 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ 長さがContent-Length からわかる
  26. 66 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ 指定されたByte数読み込む
  27. 67 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ 指定されたByte数読み込む awkにそんな機能はない🥺
  28. 68 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ でも諦めたくない
  29. 69 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ でも諦めたくない gawkなら、頑張ればできる
  30. 70 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ”\r\n” 入力の区切り文字 (一回の入力で どこまで読むかを宣言)
  31. 71 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... 入力の区切り文字 (一回の入力で どこまで読むかを宣言)
  32. 72 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... gawkでは区切り文字を 正規表現にできる
  33. 73 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... gawkでは区切り文字を 正規表現にできる ” . ” … 任意の一文字
  34. 74 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... 入力の1文字目を 区切り文字にする
  35. 75 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”...
  36. 76 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... getlineを一回呼ぶと
  37. 77 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... 入力結果 $0 は空 区切り文字は t
  38. 78 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... 入力結果 $0 は空 区切り文字は t ← RT に記録される
  39. 79 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” . ”... 1Byte読めた😃
  40. 80 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ”
  41. 81 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ” getlineを一回呼ぶと
  42. 82 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ” 82 入力結果 $0 は空 区切り文字は title=YAPC&content=%E6% ↑ RT に記録される
  43. 83 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ” ボディを読めた😃
  44. 84 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ” ボディを読めた😃 読めて欲しかった
  45. 85 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{41} ” ボディを読めた😃 動かない🥺
  46. 86 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” なぜか、ボディ末尾に 差し掛かると止まる🥺 86 86 ↓読み込めない
  47. 87 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” 87 87 ↓読み込めない 原因不明🥺
  48. 88 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” 88 88 ↓読み込めない オワタ\(^o^)/
  49. 89 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” 89 89 ↓読み込めない 諦める
  50. 90 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” 90 90 ↓読み込めない 後ろの方は読まない
  51. 91 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21 ヘッダ ボディ RS = ” .{??} ” 91 91 ↓読み込めない 内容が欠けると困る
  52. 92 HTTPリクエストヘッダ POST /articles HTTP/1.1 Host: example.com Content-Length: 41 Content-Type:

    application/x-www-form-urlencoded Accept: text/html title=YAPC&content=%E6%9C%80%E9%AB%98%21xx ヘッダ ボディ RS = ” .{??} ” 92 92 ↓読み込めない 内容が欠けると困る →事前に、不要な文字を足しておく
  53. 96 HTTPリクエストボディ クライアント (Webブラウザ) サーバ (gawk) リバースプロキシ (Nginx) Nginxは proxy_set_body

    という設定で、ボディを加工できる title=YAPC::Hiroshima2024&co ntent=%E6%9C%80%E9%AB% 98%21 title=YAPC::Hiroshima2024&co ntent=%E6%9C%80%E9%AB% 98%21_____________________ __________________________ __________________________ __________________________ _… title=YAPC::Hiroshima2024&co ntent=%E6%9C%80%E9%AB% 98%21_____________________ __________________________ __________________________ __________________________ _… 全部読み込まずに レスポンスを返す
  54. 104 その他 PostgreSQLとの通信 - gawkはC言語で拡張を書ける - 公式の拡張 gawkextlib ↑PostgreSQLクライアントもある -

    ビルド済みのDockerイメージを公開中 yammerjp/gawk-pgsql-docker https://github.com/yammerjp/gawk-pgsql-docker
  55. 109 その他 画像アップロード - awkはバイナリを扱うのが難しい - Amazon S3の署名付きアップロード を利用 -

    OpenSSLコマンドを組み合わせ、 awkプログラム内で署名を生成する - オブジェクトストレージ最高!
  56. 110 その他 URLデコード - ブラウザのフォーム送信を受け取り - UTF-8のバイト列規則に従い変換 %E3%81%82 → あ

    余談: awkblogにはJSON APIもあるが、JSON デコードはgawkextlibのJSON拡張を利用