怎么编写去语言中间件

  介绍

这篇文章主要介绍怎么编写去语言中间件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

<强>引言

web开发的背景下,“中间件“通常意思是“包装原始应用并添加一些额外的功能的应用的一部分”。这个概念似乎总是不被人理解,但是我认为中间件非常棒。

首先,一个好的中间件有一个责任就是可插拔并且自足。这就意味着你可以在接口级别嵌入你的中间件他就能直接运行。它不会影响你编码方式,不是框架,仅仅是你请求处理里面的一层而已。完全没必要重写你的代码,如果你想使用中间件的一个功能,你就帮他插入到那里,如果不想使用了,就可以直接移除。

纵观去语言,中间件是非常普遍的,即使在标准库中,虽然开始的时候不会那么明显,在标准库net/http中的函数StripText或者TimeoutHandler就是我们要定义和的中间件的样子,处理请求和相应的时候他们包装你的处理程序,并处理一些额外的步骤。

一开始,我们认为编写中间件似乎很容易,但是我们实际编写的时候也会遇到各种各样的坑。让我们来看看一些例子。

<强> 1,读取请求

在我们的示例中,所有的中间件都将接受http。处理程序作为一个参数,并返回一个http。处理程序。这使得人们很容易就能把中间产品串起来。我们所有的中间产品的基本模式是这样的:

func  X (h  http.Handler), http.Handler  {   ,return  http.HandlerFunc (func (w  http.ResponseWriter, r  * http.Request), {   ,//Something 这里…   ,h.ServeHTTP (w, r)   ,})   }

我们想要将所有的请求重定向到一个斜杠——比方说//消息,到它们的非斜杠等效,比如/消息。我们可以这样写:

func  TrailingSlashRedirect (h  http.Handler), http.Handler  {   ,return  http.HandlerFunc (func (w  http.ResponseWriter, r  * http.Request), {   ,if  r.URL.Path  !=,“/?,,, r.URL.Path len (r.URL.Path) [1],==, & # 39;/& # 39;, {   ,http.Redirect (w, r, r.URL.Path: len (r.URL.Path) 1,, http.StatusMovedPermanently)   ,返回   ,}   ,h.ServeHTTP (w, r)   ,})   }

有没有很简单。

<强> 2,修改请求

比方说,我们想要向请求添加一个标题,或者修改它.http.Handler文档中指明:

除了读取主体之外,处理程序不应该修改所提供的请求。

去标准库复制http。请求。请求对象在将其传递到响应链之前,我们也应该这样做。假设我们想在每个请求上设置请求id头,以便内部跟踪。创建*请求的浅副本,并在代理之前修改标题。

func  RequestID (h  http.Handler), http.Handler  {   ,return  http.HandlerFunc (func (w  http.ResponseWriter, r  * http.Request), {   ,r2 :=,新(http.Request)=,*,* r2  r   ,r2.Header.Set (“X-Request-Id", uuid.NewV4 () .String ())   ,h.ServeHTTP (w, r2)   ,})   }

<强> 3,编写响应头

如果你想设置响应头,你可以只写它们,然后代理请求。

func 服务器(h  http.Handler, servername 字符串),http.Handler  {   ,return  http.HandlerFunc (func (w  http.ResponseWriter, r  * http.Request), {   这里,w.Header () (“Server",, servername)   ,h.ServeHTTP (w, r)   ,})   }

上面的问题是,如果内部处理器也设置了服务器头,那么你的头将被覆盖。如果不想公开内部软件的服务器头,或者如果想在发送响应给客户端之前去掉头部,这可能会带来问题。

要做到这一点,我们必须自己实现ResponseWriter接口。大多数时候,我们只会代理到底层的ResponseWriter,但是如果用户试图写一个响应,我们就会潜入并添加我们的标题。

type  serverWriter  struct  {   w  http.ResponseWriter   name 字符串   wroteHeaders 保龄球   }      func  (s  * serverWriter),标题(),http.Header  {   ,return  s.w.Header ()   }      func  (s  * serverWriter), WriteHeader (code  int), http.Header  {   ,if  s.wroteHeader ==, false  {   这里,s.w.Header () (“Server",, s.name)   s.wroteHeader =, true   ,}   ,s.w.WriteHeader(代码)   }      func  (s  * serverWriter),写(b []字节),(int,错误),{   ,if  s.wroteHeader ==, false  {   ,//hit 我方表示歉意却;能够case  if  user  never  calls  WriteHeader  (default  200)   这里,s.w.Header () (“Server",, s.name)   s.wroteHeader =, true   ,}return  s.w.Write (b)   }

怎么编写去语言中间件