🤐

Vercelでアーカイブファイルを取ってきてファイルサーバーにする

2023/05/05に公開

https://vercel.com/docs/storage

Vercel Storageが思っていたのと違っていたのでそれっぽいものを作りました。

main.go
package handler

import (
	"net/http"
	"os"
	"os/exec"
)

func Handler(w http.ResponseWriter, r *http.Request) {
	if _, err := os.Stat("/tmp/v0.9.0.tar.gz"); err != nil {
		exec.Command("mkdir", "-p", "/tmp/fs").Run()
		exec.Command("curl", "-sLo", "/tmp/v0.9.0.tar.gz", "https://github.com/golang/net/archive/refs/tags/v0.9.0.tar.gz").Run()
		exec.Command("tar", "-xzf", "/tmp/v0.9.0.tar.gz", "--strip-components=1", "-C", "/tmp/fs").Run()
	}
	http.FileServer(http.Dir("/tmp/fs")).ServeHTTP(w, r)
}
vercel.json
{
  "builds": [
    { "src": "main.go", "use": "@vercel/go" }
  ],
  "routes": [
    { "src": "/(.*)", "dest": "main.go" }
  ]
}

こうすることで/tmpディレクトリにtar.gzファイルがない場合、curlコマンドで取ってきてtarコマンドで展開してGoのhttpパッケージでファイルサーバーにすることができます。
/tmpディレクトリにファイルを常時置いておくことはできないので、アーカイブファイルが存在しないときだけ取ってくることにしました。

https://vercel.com/guides/how-can-i-use-files-in-serverless-functions

/tmpディレクトリを一時的なストレージとして使う方法はVercelがZeit Nowと呼ばれていた頃からあって、特に新しい機能ではないのですが、今回Vercel KVとVercel Postgresを使い、うまくいかなかった点を補完する時思いついたので残しておきたいと思います。

以下のページで実際に動いている様子を確認できます。

https://tmpfs.vercel.app/

Discussion