golangで書いたスクリプトまとめ

Golangの勉強で書いたコードについて挙げます。

pgmot/imagine

これは画像アップローダーです。短いコードなのでガッと載せます。

package main

import (
    "crypto/rand"
    "encoding/base64"
    "io"
    "log"
    "net/http"
    "os"
    "path/filepath"
    "strings"

    "github.com/gin-gonic/gin"
)

func main() {
    port := os.Getenv("PORT")

    if port == "" {
        log.Fatal("$PORT must be set")
    }

    router := gin.Default()

    router.Static("/", "./images")
    router.POST("/upload", func(c *gin.Context) {
        file, header, err := c.Request.FormFile("image")
        fileExt := filepath.Ext(header.Filename)

        b := make([]byte, 40)
        rand.Read(b)
        randomName := base64.URLEncoding.EncodeToString(b)
        out, err := os.Create("./images/" + randomName + strings.ToLower(fileExt))

        if err != nil {
            log.Print(err)
            c.Err()
        }
        defer out.Close()

        _, err = io.Copy(out, file)
        if err != nil {
            log.Print(err)
            c.Err()
        }

        c.String(http.StatusOK, randomName+strings.ToLower(fileExt))
    })

    router.Run(":" + port)
}

まず、 router には2つのエンドポイントが設定されます。一つは /upload です。これは名前の通りPOSTで画像を受けて実行しているサーバの ./images/ 以下に適当なハッシュをつけて保存するエンドポイントです。 画像を見たいときはおもむろに /<hash>でアクセスすると見れます。ここはStaticとして設定をして実現をしていますが、サーバが画像を返すのは現実的によろしくないので、今後の課題とさせていただきます。

pgmot/hanasu

これはwebsocketでいい感じにチャットできるgolang webアプリです。 実装は、

Go言語によるWebアプリケーション開発

Go言語によるWebアプリケーション開発

これをパクって参考にしてやりました。

pgmot/dokokara

これはアクセス元IPを出すgolang webアプリです。 VPNなどを構築した後に本当にVPN越しに行けているのかの確認用に作りましたが、本当は 診断くん でなんとかしています。

package main

import (
    "fmt"
    "log"
    "net"
    "net/http"
    "os"
)

func doko(w http.ResponseWriter, r *http.Request) {
    var ip string

    ip = r.Header.Get("X-Forwarded-For")
    if ip == "" {
        var err error
        ip, _, err = net.SplitHostPort(r.RemoteAddr)
        if err != nil {
            log.Println("SplitHostPort error: ", err)
            fmt.Fprint(w, "IP: ???\nHost: ???")
            return
        }
    }
    log.Println("IP: ", ip)

    host, err := net.LookupAddr(ip)
    if err != nil {
        log.Println("LookupAddr error: ", err)
        fmt.Fprintf(w, "IP: %s\nHost: ???", ip)
        return
    }
    log.Println("Host: ", host)

    fmt.Fprintf(w, "IP: %s\nHost: %s", ip, host[0])
}

func main() {
    port := os.Getenv("PORT")

    if port == "" {
        log.Fatal("$PORT must be set")
    }

    http.HandleFunc("/", doko)
    err := http.ListenAndServe(":"+port, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

func doko 内でアクセス元の情報をもとに返してあげる実装になっています。簡単でした。

まとめと感想

Webアプリをガッツリ書くよりもAPIのためとかコマンドとして書くみたいな方が書きやすかった。一時期RailsみたいなフルスタックWAFとして使おうとしたけどなんか違う気がする。