HTTP中间件和Google Cloud Functions

huangapple go评论90阅读模式
英文:

HTTP Middleware and Google Cloud Functions

问题

在Google Cloud Functions中,与中间件处理程序相当的是云函数的中间件。以下是一个示例:

首先,在云函数中定义处理程序:

def my_receive_handler(request):
    # 处理请求的逻辑
    return 'Response'

然后,定义中间件函数:

def error_handler_middleware(request):
    try:
        response = my_receive_handler(request)
        return response
    except Exception as e:
        # 处理错误的逻辑
        print(f"An error occurred: {e}")
        return 'Internal Server Error', 500

最后,在云函数中使用中间件:

def main(request):
    return error_handler_middleware(request)

这样,当请求进入云函数时,会先经过中间件函数进行处理,然后再传递给实际的处理程序。如果在中间件函数中发生错误,将会返回一个内部服务器错误的响应。

希望对你有所帮助!

英文:

What’s the equivalent to middleware handlers in Google Cloud Functions?

In standard approach, normally I do:

router.Handle("/receive", middlewares.ErrorHandler(MyReceiveHandler))

And then, in the middleware:

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()))
}

In AWS Lambda, I can achieve the same thing using, for example:

func main() {
    lambda.Start(
        middlewares.Authentication(Handler),
    )
}

But I could not find a way to do this in GCP Functions.
How would it work?

Can you help me?

答案1

得分: 1

假设你在开发环境中有以下的服务器代码:

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,你需要显式地选择其 ServeHTTP 方法以获得预期类型的函数。然而,该标识符可以是一个包级函数、一个方法或一个变量。

以下是如何将上述代码适应于 GCF 的方法:

package p

import (
	"fmt"
	"net/http"
)

// 将 F 作为 GCF 的入口点
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!")
}

以上是将代码适配为 GCF 的方法。

英文:

Let's say you start with the following server code in your development environment:

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

As far as I can tell, GCF requires its entry point to be an exported identifier of type func(http.ResponseWriter, *http.Request) (not http.HandlerFunc, not http.Handler); therefore, if you have a http.Handler, you'll need to select its ServeHTTP method explicitly to obtain a function of the expected type. However, that identifier can be a package-level function, a method, or a variable.

Here is how you can adapt the code above for 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!")
}

huangapple
  • 本文由 发表于 2021年7月13日 03:30:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/68352990.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定