当前位置: 代码网 > it编程>前端脚本>Golang > Golang使用原生http实现中间件的代码详解

Golang使用原生http实现中间件的代码详解

2024年06月13日 Golang 我要评论
golang原生http实现中间件中间件(middleware):常被用来做认证校验、审计等大家常用的iris、gin等web框架,都包含了中间件逻辑。但有时我们引入该框架显得较为繁重,本文将介绍通过

golang原生http实现中间件

中间件(middleware):常被用来做认证校验、审计等

大家常用的iris、gin等web框架,都包含了中间件逻辑。但有时我们引入该框架显得较为繁重,本文将介绍通过golang原生http来实现中间件操作。全部代码:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/middleware

1 定义http.handler:具体中间件操作

①corsmiddleware:允许跨域

// corsmiddleware handles cross-origin resource sharing (cors) responses.
func corsmiddleware(next http.handler) http.handler {
	fmt.println("cors middleware....")
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		if r.method == "options" {
			w.header().set("access-control-allow-origin", "*")
			w.header().set("access-control-allow-methods", "get, post, options, delete")
			//如果前后端需要传递自定义请求头,需要再access-control-allow-headers中匹配(yi-auth-token)
			w.header().set("access-control-allow-headers", "content-type, accept, yi-auth-token")
			w.writeheader(http.statusok)
			return
		}
		w.header().set("access-control-allow-origin", "*")
		w.header().set("access-control-allow-methods", "get, post, options, delete")
		w.header().set("access-control-allow-headers", "content-type,accept,yi-auth-token")
		//交给下一个中间件处理
		next.servehttp(w, r)
	})
}

②authmiddleware:认证

// authmiddleware simulates a simple authentication middleware.
func authmiddleware(next http.handler) http.handler {
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		fmt.println("auth middleware...")
		//store info in ctx
		token := r.header.get("token")
		if len(token) != 0 {
			//todo 1. check token 2. get userinfo from token
			userid := "1"
			ctx := context.withvalue(r.context(), "userid", userid)
			r = r.withcontext(ctx)
		}
		next.servehttp(w, r)
	})
}

③auditmiddleware:审计操作

// auditmiddleware simulates an audit logging middleware.
func auditmiddleware(next http.handler) http.handler {
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		fmt.println("audit middleware...")
		next.servehttp(w, r)
	})
}

④smokehandler:具体处理操作

// smokehandler returns the current time as a string.
func smokehandler(w http.responsewriter, r *http.request) {
	fmt.println("smoke handle....")
	_, err := w.write([]byte(time.now().string()))
	if err != nil {
		http.error(w, "internal server error", http.statusinternalservererror)
	}
}

2 义中间件类型&定义中间件链

①type middleware func(http.handler) http.handler:定义中间件

type middleware func(http.handler) http.handler

②定义中间件链middlewarechain

// newmiddlewarechain creates a new middleware chain with the given middlewares.
func newmiddlewarechain(middlewares ...middleware) middleware {
	return func(handler http.handler) http.handler {
		for i := len(middlewares) - 1; i >= 0; i-- {
			handler = middlewares[i](handler)
		}
		return handler
	}
}

3 启动http服务

func runandserve() error {
	defer func() {
		if e := recover(); e != nil {
			fmt.println("err=", e)
		}
	}()

	mux := http.newservemux()

	// create middleware chains for routes.
	authmiddlewarechain := newmiddlewarechain(corsmiddleware, authmiddleware, auditmiddleware)
	//noauthmiddlewarechain := newmiddlewarechain(corsmiddleware)

	// convert the middleware chain result to http.handlerfunc.
	smokehandlerwrapped := func(w http.responsewriter, r *http.request) {
		authmiddlewarechain(http.handlerfunc(smokehandler)).servehttp(w, r)
	}

	mux.handlefunc("/smoke", smokehandlerwrapped)

	fmt.printf("listening on http://localhost:%d\n", 9999)
	return http.listenandserve(":9999", mux)
}

4 测试

启动后端

go run main.go

在这里插入图片描述

2. 浏览器访问http://localhost:9999/smoke

在这里插入图片描述

3. 后端日志打印

可以看到是最后才处理我们的业务handler

在这里插入图片描述

全部代码

package main

import (
	"context"
	"fmt"
	"net/http"
	"time"
)

type middleware func(http.handler) http.handler

// corsmiddleware handles cross-origin resource sharing (cors) responses.
func corsmiddleware(next http.handler) http.handler {
	fmt.println("cors middleware....")
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		if r.method == "options" {
			w.header().set("access-control-allow-origin", "*")
			w.header().set("access-control-allow-methods", "get, post, options, delete")
			//如果前后端需要传递自定义请求头,需要再access-control-allow-headers中匹配(yi-auth-token)
			w.header().set("access-control-allow-headers", "content-type, accept, yi-auth-token")
			w.writeheader(http.statusok)
			return
		}
		w.header().set("access-control-allow-origin", "*")
		w.header().set("access-control-allow-methods", "get, post, options, delete")
		w.header().set("access-control-allow-headers", "content-type,accept,yi-auth-token")
		next.servehttp(w, r)
	})
}

// authmiddleware simulates a simple authentication middleware.
func authmiddleware(next http.handler) http.handler {
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		fmt.println("auth middleware...")
		//store info in ctx
		token := r.header.get("token")
		if len(token) != 0 {
			//todo 1. check token 2. get userinfo from token
			userid := "1"
			ctx := context.withvalue(r.context(), "userid", userid)
			r = r.withcontext(ctx)
		}
		next.servehttp(w, r)
	})
}

// auditmiddleware simulates an audit logging middleware.
func auditmiddleware(next http.handler) http.handler {
	return http.handlerfunc(func(w http.responsewriter, r *http.request) {
		fmt.println("audit middleware...")
		next.servehttp(w, r)
	})
}

// smokehandler returns the current time as a string.
func smokehandler(w http.responsewriter, r *http.request) {
	fmt.println("smoke handle....")
	_, err := w.write([]byte(time.now().string()))
	if err != nil {
		http.error(w, "internal server error", http.statusinternalservererror)
	}
}

// newmiddlewarechain creates a new middleware chain with the given middlewares.
func newmiddlewarechain(middlewares ...middleware) middleware {
	return func(handler http.handler) http.handler {
		for i := len(middlewares) - 1; i >= 0; i-- {
			handler = middlewares[i](handler)
		}
		return handler
	}
}

func runandserve() error {
	defer func() {
		if e := recover(); e != nil {
			fmt.println("err=", e)
		}
	}()

	mux := http.newservemux()

	// create middleware chains for routes.
	authmiddlewarechain := newmiddlewarechain(corsmiddleware, authmiddleware, auditmiddleware)
	//noauthmiddlewarechain := newmiddlewarechain(corsmiddleware)

	// convert the middleware chain result to http.handlerfunc.
	smokehandlerwrapped := func(w http.responsewriter, r *http.request) {
		authmiddlewarechain(http.handlerfunc(smokehandler)).servehttp(w, r)
	}

	mux.handlefunc("/smoke", smokehandlerwrapped)

	fmt.printf("listening on http://localhost:%d\n", 9999)
	return http.listenandserve(":9999", mux)
}

func main() {
	runandserve()
}

以上就是golang使用原生http实现中间件的代码详解的详细内容,更多关于golang http中间件的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com