HTTP 中间件和 Google 云函数
HTTP Middleware and Google Cloud Functions
什么相当于 Google Cloud Functions 中的中间件处理程序?
在标准方法中,通常我会这样做:
router.Handle("/receive", middlewares.ErrorHandler(MyReceiveHandler))
然后,在中间件中:
type ErrorHandler func(http.ResponseWriter, *http.Request) error
func (fn ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := fn(w, r)
if err == nil {
return
}
log.Printf("An error accured: %v", err)
clientError, ok := err.(errors.BaseError)
if !ok {
w.WriteHeader(500)
return
}
w.WriteHeader(clientError.GetStatusCode())
w.Write([]byte(clientError.Error()))
}
在 AWS Lambda 中,我可以实现相同的功能,例如:
func main() {
lambda.Start(
middlewares.Authentication(Handler),
)
}
但我无法在 GCP 功能中找到执行此操作的方法。
它是如何工作的?
你能帮帮我吗?
假设您从开发环境中的以下服务器代码开始:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.Handle("/", MiddlewareFinalMsg(" Goodbye!", http.HandlerFunc(HelloWorld)))
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
func MiddlewareFinalMsg(msg string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
fmt.Fprint(w, msg)
})
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello, World!")
}
据我所知,GCF 要求其 入口点 是 func(http.ResponseWriter, *http.Request)
类型的导出标识符(不是 http.HandlerFunc
,不是 http.Handler
);因此,如果您有一个 http.Handler
,您将需要 select 其 ServeHTTP
方法明确地获得预期类型的函数。但是,该标识符可以是包级函数、方法或变量。
以下是如何为 GCF 调整上面的代码:
package p
import (
"fmt"
"net/http"
)
// use F as your GCF's entry point
var F = MiddlewareFinalMsg(" Goodbye!", http.HandlerFunc(HelloWorld)).ServeHTTP
func MiddlewareFinalMsg(msg string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
fmt.Fprint(w, msg)
})
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello, World!")
}
什么相当于 Google Cloud Functions 中的中间件处理程序?
在标准方法中,通常我会这样做:
router.Handle("/receive", middlewares.ErrorHandler(MyReceiveHandler))
然后,在中间件中:
type ErrorHandler func(http.ResponseWriter, *http.Request) error
func (fn ErrorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := fn(w, r)
if err == nil {
return
}
log.Printf("An error accured: %v", err)
clientError, ok := err.(errors.BaseError)
if !ok {
w.WriteHeader(500)
return
}
w.WriteHeader(clientError.GetStatusCode())
w.Write([]byte(clientError.Error()))
}
在 AWS Lambda 中,我可以实现相同的功能,例如:
func main() {
lambda.Start(
middlewares.Authentication(Handler),
)
}
但我无法在 GCP 功能中找到执行此操作的方法。 它是如何工作的?
你能帮帮我吗?
假设您从开发环境中的以下服务器代码开始:
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.Handle("/", MiddlewareFinalMsg(" Goodbye!", http.HandlerFunc(HelloWorld)))
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}
func MiddlewareFinalMsg(msg string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
fmt.Fprint(w, msg)
})
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello, World!")
}
据我所知,GCF 要求其 入口点 是 func(http.ResponseWriter, *http.Request)
类型的导出标识符(不是 http.HandlerFunc
,不是 http.Handler
);因此,如果您有一个 http.Handler
,您将需要 select 其 ServeHTTP
方法明确地获得预期类型的函数。但是,该标识符可以是包级函数、方法或变量。
以下是如何为 GCF 调整上面的代码:
package p
import (
"fmt"
"net/http"
)
// use F as your GCF's entry point
var F = MiddlewareFinalMsg(" Goodbye!", http.HandlerFunc(HelloWorld)).ServeHTTP
func MiddlewareFinalMsg(msg string, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
h.ServeHTTP(w, r)
fmt.Fprint(w, msg)
})
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello, World!")
}