Edited at
Go2Day 2

GoでCGIしてみる

というわけでCGIしてみます。


一般的なGoのWebアプリケーションからの置き換え

普通、GoでWebアプリケーションを作るときは、net/httpを用いてHTTPをしゃべるサーバを立てるかと思います。もしくは、各種フレームワークが同じようなことをやるでしょう。

import "net/http"

func main() {
http.ListenAndServe(
":8080",
http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
// do something
}),
)
}

CGIの場合は、Apache等のサーバがHTTPをしゃべるサーバとなり、CGIプログラムをサーバが実行します。なので、上記方法はそのまま使えません。

そこでGoにはnet/http/cgiというものがあります。これは上記net/httpListenAndServeを置き換えればいいだけです。

import (

"net/http"
"net/http/cgi"
)

func main() {
cgi.Serve(
http.HandlerFunc(func (w http.ResponseWriter, r *http.Request) {
// do something
}),
)
}


ローカルでの確認方法

現代においてはApacheを立てるというのも相対的に難儀な作業になってきました。そこでCGIアプリケーションを確認するための簡易的な方法を紹介します。

HTTPサーバミドルウェアのh2oを用います。以下の設定でCGIアプリケーションの確認ができます。

listen:

port: 8081
user: username
hosts:
"localhost":
paths:
/:
file.dir: ./
file.index: ["index.cgi"]
file.custom-handler:
extension: .cgi
fastcgi.spawn:
command: "exec $H2O_ROOT/share/h2o/fastcgi-cgi"

access-log: log/access-log
error-log: log/error-log
pid-file: log/pid-file

以上をh2o.ymlで保存し、

$ h2o -c h2o.yml

で起動します。GoのCGIアプリケーションはindex.cgiで保存しておきます。もちろんパーミッションは実行可能にしておきます。これで簡単にローカルでCGIアプリケーションの確認ができます。


実際のCGIアプリケーションを作ってみる

https://gist.github.com/mackee/2247f081ad860ed36c7b27bb6886b862

というわけで作ってみました。

image.png

頑張ってる点としては


  • カウンタがファイルサイズで記録して追記で済ませるタイプ

  • コメント欄はファイル記録


    • 当時は考えていなかったCSRFだとかを考えないといけない

    • XSSはhtml/templateがある程度防御してくれている



  • ログはファイルに書いておいてレンタルサーバでデバッグしやすくする

という感じです。


まとめ


  • 簡単にですがGoでCGIについて説明しました

  • コンテナだとかサーバレスだとかはCGIっぽいアーキテクチャかと思います。CGIで済むのであればCGIでプライベートサーバレス環境を作ってみると面白いかと思います