Golang中实现简单的Http Middleware

本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下

首先, 我定义了三个测试的中间件 Middleware1,2,3 如下

func Middleware1(next http.Handler) http.Handler {

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("M1 in")
		next.ServeHTTP(w, r)
		fmt.Println("M1 out")
	})

}

func Middleware2(next http.Handler) http.Handler {

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("M2 in")
		next.ServeHTTP(w, r)
		fmt.Println("M2 out")
	})

}

func Middleware3(next http.Handler) http.Handler {

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Println("M3 in")
		next.ServeHTTP(w, r)
		fmt.Println("M3 out")
	})

}

这里中间件的入参和出参的类型都是 http.Handler, 然后在 next.ServeHTTP() 的前后分别输出了 In 和 Out.

接下来,定义一个 Pipeline 的方法,里面使用嵌套的形式, 使用了上面定义的三个测试的中间件.

func Pipeline(next http.Handler) http.Handler {

	return Middleware1(Middleware2(Middleware3(next)))

}

然后还需要业务代码,这里我定义了 LoginHandler 和 RegisterHandler 两个方法

func LoginHandler(w http.ResponseWriter, r *http.Request) {

	fmt.Println("Login...")
	w.Write([]byte("Login..."))

}

func RegisterHandler(w http.ResponseWriter, r *http.Request) {

	fmt.Println("Register...")
	w.Write([]byte("Register..."))

}

最后修改程序的 main 函数, 在 Login 接口上使用上面添加过中间件的 Pipeline

func main() {

	http.Handle("/Login", Pipeline(http.HandlerFunc(LoginHandler)))

	http.Handle("/Register", http.HandlerFunc(RegisterHandler))

	http.ListenAndServe(":8080", nil)

}

启动程序后,访问 http://localhost:8080/Login, 程序的输出如下,这和本文最上面的管道的流程图是一致的,然后访问 Register 接口, 控制台没有输出信息,当然也不会执行任何中间件。

现在已经实现了中间件的机制,但是,上面添加中间件是用嵌套的方法,这种方式不能说不太优雅,只能说非常的Low,接下来我们需要对管道进行优化

type Chain struct {
	middlewares []func(handler http.Handler) http.Handler
}

func Pipeline(next http.Handler) http.Handler {

	//return Middleware1(Middleware2(Middleware3(next)))

	return AddMiddlewares(Middleware1,Middleware2,Middleware3).Then(next)

} 

func AddMiddlewares(m ...func(handlerFunc http.Handler) http.Handler) Chain {

	c := Chain{}

	c.middlewares = append(c.middlewares,m...)

	return c

}

func (c Chain) Then(next http.Handler) http.Handler {

	for i := range c.middlewares {

		prev := c.middlewares[len(c.middlewares)-1-i]

		next = prev(next)
	}

	return next
} 

首先定义了一个Chain 的struct,用来接收添加到管道中的中间件,在 AddMiddlewares() 函数中,接收了多个Handle, 然后组装到 Chain 对象并返回, 接下来调用 Then() 函数, 把管道中的中间件和业务的Handler 关联起来。在中间件的使用方式上, 这两种方法都是一样的,只需要调用 Pipeline() 方法就行了。

本文在go web中简单的实现了中间件的机制,这样带来的好处也是显而易见的,当然社区也有一些成熟的 middleware 组件,包括 Gin 一些Web框架中也包含了 middleware 相关的功能, 希望对您有用.

到此这篇关于Golang中实现简单的Http Middleware的文章就介绍到这了,更多相关Golang实现Http Middleware内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Django使用HttpResponse返回图片并显示的方法

    做了一个关于Django的小案例,想要在网页中显示图片,直接在img标签的src属性写图片的路径是不能显示的,查询资料发现在Django中使用图片这类的资源相当繁琐需要进行一定D的配置,摸索了一会没有整明白,想到了写Java时使用文件流返回图片,于是想到使用该种方式来显示图片. 使用实例如下: views.py def my_image(request,news_id): d = path.dirname(__file__) #parent_path = path.dirname(d) prin

  • Go语言的http/2服务器功能及客户端使用

    前言 大家都知道,Go的标准库HTTP服务器默认支持HTTP/2.那么,在这篇文章中,我们将首先展示Go的http/2服务器功能,并解释如何将它们作为客户端使用. 在这篇文章中,我们将首先展示Go的http/2服务器功能,并解释如何将它们作为客户端使用.Go的标准库HTTP服务器默认支持HTTP/2. 下面话不多说了,来一起看看详细的介绍吧 HTTP/2 服务器 首先,让我们在Go中创建一个http/2服务器!根据http/2文档,所有东西都是为我们自动配置的,我们甚至不需要导入Go的标准库ht

  • Go语言中利用http发起Get和Post请求的方法示例

    关于 HTTP 协议 HTTP(即超文本传输协议)是现代网络中最常见和常用的协议之一,设计它的目的是保证客户机和服务器之间的通信. HTTP 的工作方式是客户机与服务器之间的 "请求-应答" 协议. 客户端可以是 Web 浏览器,服务器端可以是计算机上的某些网络应用程序. 通常情况下,由浏览器向服务器发起 HTTP 请求,服务器向浏览器返回响应.响应包含了请求的状态信息以及可能被请求的内容. Go 语言中要请求网页时,使用net/http包实现.官方已经提供了详细的说明,但是比较粗略,

  • go语言在请求http时加入自定义http header的方法

    本文实例讲述了go语言在请求http时加入自定义http header的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: client := &http.Client{] req, err := http.NewRequest("POST", "http://example.com", bytes.NewReader(postData)) req.Header.Add("User-Agent", "myCli

  • golang的HTTP基本认证机制实例详解

    本文实例讲述了golang的HTTP基本认证机制.分享给大家供大家参考,具体如下: 看了<<http权威指南>>第12章HTTP基本认证机制(本站下载地址:http://www.jb51.net/books/93254.html),感觉讲的蛮详细的,写了一个小小例子测试. 请求响应过程: 复制代码 代码如下: ==> GET /hello HTTP/1.1 Host: 127.0.0.1:12345 <== HTTP/1.1 401 Unauthorized WWW-A

  • Go语言服务器开发实现最简单HTTP的GET与POST接口

    本文实例讲述了Go语言服务器开发实现最简单HTTP的GET与POST接口.分享给大家供大家参考.具体分析如下: Go语言提供了http包,可以很轻松的开发http接口.以下为示例代码: 复制代码 代码如下: package webserver    import (      "encoding/json"      "fmt"      "net/http"      "time"  )    func WebServerB

  • 一个简单的Golang实现的HTTP Proxy方法

    最近因为换了Mac,以前的Linux基本上不再使用了,但是我的SS代理还得用.SS代理大家都了解,一个很NB的socks代理工具,但是就是因为他是Socks的,想用HTTP代理的时候很不方便. 以前在Linux下的时候,会安装一个Privoxy把socks代理转换为HTTP代理,开机启动,也比较方便.但是Mac下使用Brew安装的Privoxy就很难用,再加上以前一个有个想法,一个软件搞定socks和HTTP代理,这样就不用安装一个单独的软件做转换了. 想着就开始做吧,以前基本上没有搞过太多的网

  • Golang中实现简单的Http Middleware

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下 首先, 我定义了三个测试的中间件 Middleware1,2,3 如下 func Middleware1(next http.Handler) http.Handler { return http.HandlerFunc(func(w

  • Golang中基础的命令行模块urfave/cli的用法说明

    前言 相信只要部署过线上服务,都知道启动参数一定是必不可少的,当你在不同的网络.硬件.软件环境下去启动一个服务的时候,总会有一些启动参数是不确定的,这时候就需要通过命令行模块去解析这些参数,urfave/cli是Golang中一个简单实用的命令行工具. 安装 通过 go get github.com/urfave/cli 命令即可完成安装. 正文 使用了urfave/cli之后,你的程序就会变成一个命令行程序,以下就是通过urfave/cli创建的一个最简单的命令行程序,它设定了一些基础的信息,

  • 在 Golang 中实现一个简单的Http中间件

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下 首先, 我定义了三个测试的中间件 Middleware1,2,3 如下 func Middleware1(next http.Handler) http.Handler { return http.HandlerFunc(func(w

  • 在 Golang 中实现一个简单的Http中间件过程详解

    本文主要针对Golang的内置库 net/http 做了简单的扩展,通过添加中间件的形式实现了管道(Pipeline)模式,这样的好处是各模块之间是低耦合的,符合单一职责原则,可以很灵活的通过中间件的形式添加一些功能到管道中,一次请求和响应在管道中的执行过程如下 首先, 我定义了三个测试的中间件 Middleware1,2,3 如下 func Middleware1(next http.Handler) http.Handler { return http.HandlerFunc(func(w

  • 浅谈Golang中创建一个简单的服务器的方法

    我们知道,golang中的net/http包对网络的支持非常好,这样会让我们比较容易的建立起一个相对简单的服务器,我们来看一段代码 func sayHi(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w,"Hi") } func main() { http.HandleFunc("/sayHi", sayHi) log.Fatal(http.ListenAndServe("localhost:80

  • 简单聊聊Golang中defer预计算参数

    目录 什么是defer Go语言defer预计算参数 总结 什么是defer defer用来声明一个延迟函数,把这个函数放入到一个栈上, 当外部的包含方法return之前,返回参数到调用方法之前调用,也可以说是运行到最外层方法体的"}"时调用.我们经常用他来做一些资源的释放,比如关闭io操作 func doSomething(fileName string) { file,err := os.Open(fileName) if err != nil { panic(err) } def

  • golang中select语句的简单实例

    目录 前言 1.先举个简单例子 2. 避免造成死锁 3. select 随机性 4. select 的超时 5. 读取/写入都可以 6. 总结一下 前言 在golang语言中,select语句 就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作.有了 select语句,可以实现 main主线程 与 goroutine线程 之间的互动. select { case <-ch1 : // 检测有没有数据可读 // 一旦成功读取到数据,则进行该case处理语句 cas

  • Golang中Gin框架的使用入门教程

    目录 安装与简单测试 常见请求与分组请求 获取参数 与 参数合法性验证 获得query中参数 获得multipart/urlencoded form中的参数 模型绑定和参数验证 自定义参数验证 项目结构参考 Gin框架运行模式 Gin如何获取客户ip Gin处理请求结果 以String类型响应请求 以Json格式响应请求 以文件形式响应请求 设置http响应头 Gin处理html模板 Gin访问静态资源文件 Gin处理Cookie操作 Gin文件上传 Gin中间件 官方地址:gin-gonic.

  • Golang中如何使用lua进行扩展详解

    前言 最近在项目中需要使用lua进行扩展,发现github上有一个用golang编写的lua虚拟机,名字叫做gopher-lua.使用后发现还不错,借此分享给大家,下面话不多说了,来一起看看详细的介绍吧. 数据类型 lua中的数据类型与golang中的数据类型对应关系作者已经在文档中说明,值得注意的是类型是以L开头的,类型的名称是以LT开头的. golang中的数据转换为lua中的数据就必须转换为L开头的类型: str := "hello" num := 10 L.LString(st

  • Golang中数据结构Queue的实现方法详解

    前言 本文主要给大家介绍了关于Golang中数据结构Queue实现的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 需求 队列的特性较为单一,基本操作即初始化.获取大小.添加元素.移除元素等.最重要的特性就是满足先进先出. 实现 接下来还是按照以前的套路,一步一步来分析如何利用Go的语法特性实现Queue这种数据结构. 定义 首先定义每个节点Node结构体,照例Value的值类型可以是任意类型,节点的前后指针域指针类型为node type node struct {

随机推荐