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!")
}