GCPのCloud FunctionsのHTTPトリガーをGolangで使っているときにEcho使えるんじゃないかと思って試したメモです。
プロジェクト構成
Cloud Functionsで使えるように以下のようにファイルとディレクトリを作成します。
プロジェクトルート/
├── cmd
│ └── main.go
├── functions.go
├── go.mod
├── go.sum
└── shared
└── echo.go
コード
go.mod
使った依存ライブラリはこんな感じです。
module github.com/sert-uw/go_echo_functions
go 1.13
require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/labstack/echo v3.3.10+incompatible
github.com/labstack/gommon v0.3.0 // indirect
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect
golang.org/x/text v0.3.2 // indirect
)
shared/echo.go
Echoの初期化をInitEcho
で行うよう実装します。
package shared
import (
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"net/http"
)
var EchoServer *echo.Echo
func InitEcho() {
EchoServer = echo.New()
EchoServer.Use(middleware.CORSWithConfig(middleware.CORSConfig{
AllowOrigins: []string{"*"},
}))
EchoServer.GET("/hello/:name", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello "+c.Param("name"))
})
}
functions.go
init
でshared
パッケージのInitEcho
を呼び出すことでCloud Functionsの関数インスタンス作成時にEchoの設定を行います。
Function
で受け取ったHTTPリクエストはそのままEchoのServeHTTP
に渡します。
あとはEchoでリクエストを処理してくれるので、Function
の役割はこれだけです。
package functions
import (
"github.com/sert-uw/go_echo_functions/shared"
"net/http"
)
func init() {
shared.InitEcho()
}
func Function(w http.ResponseWriter, r *http.Request) {
shared.EchoServer.ServeHTTP(w, r)
}
cmd/main.go
Cloud Functionsではmain関数は使わないですが、ローカル環境で試すのに便利なので実装します。
init
でshared
パッケージのInitEcho
を呼び出してEchoの設定を行い、main
でEchoサーバーを起動するだけです。
package main
import (
"github.com/sert-uw/go_echo_functions/shared"
"log"
)
func init() {
shared.InitEcho()
}
func main() {
log.Fatalln(shared.EchoServer.Start(":8080"))
}
動作確認
ローカル環境
main関数を実行して、curlを投げてみます。
$ go run cmd/main.go
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080
$ curl 'http://localhost:8080/hello/Sert' -v
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /hello/Sert HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: *
< Content-Type: text/plain; charset=UTF-8
< Vary: Origin
< Date: Sun, 31 May 2020 16:40:27 GMT
< Content-Length: 10
<
* Connection #0 to host localhost left intact
Hello Sert
Cloud Functions
ソースコードはGCPのリポジトリにpushして以下のように設定しました。
GCPのコンソール上でトリガーのエンドポイントを確認してcurlを投げてみます。
$ curl 'https://asia-northeast1-<プロジェクト名>.cloudfunctions.net/go-echo-functions/hello/Sert' -v
* Trying 216.239.xxx.xxx...
* TCP_NODELAY set
* Connected to asia-northeast1-<プロジェクト名>.cloudfunctions.net (216.239.xxx.xxx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
* subject: C=US; ST=California; L=Mountain View; O=Google LLC; CN=misc.google.com
* start date: May 5 08:23:30 2020 GMT
* expire date: Jul 28 08:23:30 2020 GMT
* subjectAltName: host "asia-northeast1-<プロジェクト名>.cloudfunctions.net" matched cert's "*.cloudfunctions.net"
* issuer: C=US; O=Google Trust Services; CN=GTS CA 1O1
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fbd30006c00)
> GET /go-echo-functions/hello/Sert HTTP/2
> Host: asia-northeast1-<プロジェクト名>.cloudfunctions.net
> User-Agent: curl/7.54.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2 200
< access-control-allow-origin: *
< content-type: text/plain; charset=UTF-8
< function-execution-id: sdtxd0pn5lgn
< vary: Origin
< x-cloud-trace-context: 42b67e55066cded12f14db38b8da2855;o=1
< date: Sun, 31 May 2020 16:42:41 GMT
< server: Google Frontend
< content-length: 10
< alt-svc: h3-27=":443"; ma=2592000,h3-25=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
<
* Connection #0 to host asia-northeast1-<プロジェクト名>.cloudfunctions.net left intact
Hello Sert
まとめ
予想以上に簡単にEchoを動かせたので、App Engineを別のアプリケーションに使いたい場合にAPIをCloud Functionsで動かすなど、コストを抑えるためにGCPの無料枠をうまく使う選択肢の1つになるかもしれません。