首页 > 其他分享 >go web学习(四)

go web学习(四)

时间:2023-05-22 12:34:58浏览次数:37  
标签:web http Context Request 学习 func go ResponseWriter

中间件

什么是中间件

请求————> 中间件 ————> Handler
响应 <———— Middleware <———— Handler

创建中间件

func ListenAndServe(addr string, handler Handler) error
handler 如果是 nil:DefaultServeMux

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
  }

type MyMiddleware struct {
	Next http.Handler
  }
func(m MyMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// 在 next handler 之前做一些事情
m.Next.ServeHTTP(w, r)
// 在 next handler 之后做一些事情
  }

中间件的用途

Logging
安全
请求超时
响应压缩

下面是例子

// 目录下
// middleware文件夹 包含auth.go
// main.go
auth.go

package middleware
import "net/http"

// 链式结构, Next 设置为 什么,下一个handler 就是什么
// AuthMiddleware ..
type AuthMiddleware struct {
	Next http.Handler
}

func (am *AuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	// 如果只有一个中间件,改中间件的字段next 为nil, 交给默认路由器处理
	if am.Next == nil {
		am.Next = http.DefaultServeMux
	}
	// 判断auth
	auth := r.Header.Get("Authorization")
	if auth != "" {
		// before 路由
		am.Next.ServeHTTP(w, r)
		// after 路由
	} else {
		w.WriteHeader(http.StatusUnauthorized)
	}
}


main.go
package main

import (
	"encoding/json"
	"net/http"
	"timer/goWeb-sql/middleware"
    //middleware文件夹的位置,每个人都不一样,自己建的
)
type Company struct {
	ID      int
	Name    string
	Country string
}
func main(){
http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request){
    c := Company{
		ID:      123,
		Name:    "goolle",
		Country: "USA",
	}
	// time.Sleep(4*time.Second)
	enc := json.NewEncoder(w)
	enc.Encode(c)
    })
	// 通过认证就能获取数据
	// 使用中间件
http.ListenAndServe("localhost:8080", new(middleware.AuthMiddleware))
}


GET http://localhost:8080/companies HTTP/1.1

# with auth
GET http://localhost:8080/companies HTTP/1.1
Authorization: root

这个是加上请求上下文的

// 目录下
// middleware文件夹 包含auth.go timeout.go
// main.go

timeout.go

package middleware

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

type TimeoutMiddleware struct {
	Next http.Handler
}
func (tm TimeoutMiddleware) ServeHTTP(w http.ResponseWriter ,r *http.Request){
	if tm.Next == nil{
		tm.Next = http.DefaultServeMux
	}

	ctx:= r.Context()
	ctx,_ = context.WithTimeout(ctx,3*time.Second)
	r.WithContext(ctx)
	ch:= make(chan struct{})
	go func(){
		tm.Next.ServeHTTP(w,r)
		ch <- struct{}{}
	}()
	select{
	case <- ch:
		return
	case<- ctx.Done():
		w.WriteHeader(http.StatusRequestTimeout)
	}
ctx.Done()
}

main.go

http.HandleFunc("/companies", func(w http.ResponseWriter, r *http.Request) {
		c := Company{
			ID:      123,
			Name:    "gggoolle",
			Country: "USA",
		}
		// time.Sleep(4*time.Second) 用来测试的
		enc := json.NewEncoder(w)
		enc.Encode(c)
	})
	// 使用中间件
	http.ListenAndServe("localhost:8080", &middleware.TimeoutMiddleware{
	Next: new(middleware.AuthMiddleware),
	})

请求上下文

(例子见上面那个)
请求可能会通过中间件,到达handler,再到model层(数据库,Web Api,文件系统),model层不应该知道在web请求的上下文操作,但是他们需要知道一些重要信息,比如超时停摆。
它可以用于在不同的 Goroutine 之间传递请求特定值、取消信号以及超时截止日期等数据,以协调 Goroutine 之间的操作。

request Context

func(*Request) Context() context.Context
返回当前请求的上下文
func(*Request) WithContext(ctx context.Context) context.Context
基于 Context 进行“修改”,(实际上)创建一个新的 Context

context.Context

type Context interface {
	Deadline() (deadline time.Time, ok bool)
    //返回 完成工作的截止日期
	Done() <-chan struct{}
    //返回一个 Channel,这个 Channel 会在当前工作完成或者上下文被取消后关闭,
	//多次调用 Done 方法会返回同一个 Channel
	Err() error
    // 错误
	Value(key interface{}) interface{}
    // 从 context.Context中获取键对应的值
  }
//这些方法都是用于读取,不能进行设置

Context API – 可以返回新 Context

WithCancel(),它有一个 CancelFunc
WithDeadline(),带有一个时间戳(time.Time)
WithTimeout(),带有一个具体的时间段(time.Duration)
WithValue(),在里面可以添加一些值

串联处理器和处理器函数

诸如日志,安全检查和错误处理,为了防止代码重复和代码依赖,可以使用串联技术分隔它们。
也叫做管道处理
输入——》f1 do something ——》f2 do something ——》f3 do something ——》输出
和中间件相像又不一样

串联处理器函数

// http.HandleFunc("/hello",protect(log(hello)))

func hello(w http.ResponseWriter,r *http.Request){
    //
}
func log(h http.HandlerFunc) http.HandlerFunc{
    return func(w http.ResponseWriter,r *http.Request){
        //日志操作
        h(w,r)
    }
}

func protect(h http.HandlerFunc) http.HandlerFunc{
    return func(w http.ResponseWriter,r *http.Request){
        //一些操作
        h(w,r)
    }
}

串联处理器

// http.Handle("/hello",protect(log(hello)))
type HelloHandler struct{}
func (h HelloHandler) ServeHttp (w http.ResponseWriter,r *http.Request){

}
func log(h HelloHandler) http.Handler{
    return http.HandlerFunc(
        func(w http.ResponseWriter,r *http.Request){
        //一些操作
        h.ServeHttp(w,r)
    }
    )
}
func protectlog(h HelloHandler) http.Handler{
    return http.HandlerFunc(
        func(w http.ResponseWriter,r *http.Request){
        //一些操作
        h.ServeHttp(w,r)
    }
    )
}

标签:web,http,Context,Request,学习,func,go,ResponseWriter
From: https://www.cnblogs.com/tiangong/p/17420300.html

相关文章

  • WEB漏洞—简要SQL注入
    前言:在本系列课程学习中,SQL注入漏洞将是重点部分,其中SQL注入又非常复杂,区分各种数据库类型,提交方法,数据类型等注入,需要按部就班的学习,才能学会相关SQL注入的核心。同样此类漏洞是WEB安全中严重的安全漏洞,学习如何利用,挖掘,修复也是很重要的。 SQL注入安全测试中危害:危害数据和......
  • MySQL注入点写入WebShell的几种方式
    在工具化日益成熟的今天,手工注入的能力越来越被忽视了。当你掌握了一款工具的使用时,应更深入的去了解工具帮你做了什么,把工具所产生的影响控制在自己可控的范围内。比如:当面对一个MySQL注入点,通过使用SQLmap的--os-shell命令选项,便可轻松一键获取Webshell,但是非正常退出时,便会在网......
  • 机器学习数据顺序随机打乱:Python实现
      本文介绍基于Python语言,实现机器学习、深度学习等模型训练时,数据集打乱的具体操作。1为什么要打乱数据集  在机器学习中,如果不进行数据集的打乱,则可能导致模型在训练过程中出现具有“偏见”的情况,降低其泛化能力,从而降低训练精度。例如,如果我们做深度学习的分类,其中初始......
  • 【linux学习】mac启动ftp命令
    macOS默认关掉了FTP服务启动FTP服务终端命令:sudo-slaunchctlload-w/System/Library/LaunchDaemons/ftp.plist输入该命令之后,终端还会要求输入你的mac的密码。关闭FTP服务终端命令:sudo-slaunchctlunload-w/System/Library/LaunchDaemons/ftp.plist......
  • 【Git学习】git log自定义格式
    定制自己常用格式:1、二进制作者时间提交备注gitlog–pretty=format:”%h-%an,%ar:%s”2、以图表形式查看远程提交记录gitlog–decorate–oneline–graph3、说明:常用的格式占位符写法及其代表的意义。选项说明%H提交对象(commit)的完整哈希字串%h提交对象的简短......
  • Django-验证码功能
    #安装django-simple-captchapipinstalldjango-simple-captcha#settings.pyINSTALLED_APPS=[#...'captcha',]#urls.pyfromcaptcha.viewsimportcaptcha_imagefromdjango.urlsimportpathfrom.viewsimportlogin_viewurlpatterns=[path(......
  • 【研究生学习】Transformer模型以及Pytorch实现
    Transformer是Google在2017年提出的网络架构,仅依赖于注意力机制就可以处理序列数据,从而可以不使用RNN或CNN。当前非常热门的BERT模型就是基于Transformer构建的,本篇博客将介绍Transformer的基本原理,以及其在Pytorch上的实现。......
  • 信息收集学习笔记总结
    1.域名信息(来自csdn)在渗透测试过程中,一般在目标的主站很少有发现漏洞点的存在,这时候我们就要从从主站之外的接口进行渗透测试,这时我们可以从域名出发收集信息。(1)端口一个网站可能会开放多个不同的端口,而我们可以通过同一网站的不同端口进行测试,扫描开放端口的......
  • 改进django rest framework中的token验证,并加入cache
        在用户验证方面用到token验证,这是一种安卓/iso/..手机客户端常用的,方便的验证方式。原理是客户端给我发一段字符串,这段字符串是用户在注册,登入的时候、服务器生成的,并关联到用户。保存到数据库,然后返回给客户端,客户端之后呢,就可以凭借这个字符串来确认“我是我,不是别人......
  • 利用 Django REST framework 编写 RESTful API
        自动生成符合RESTful规范的API支持OPTION、HEAD、POST、GET、PATCH、PUT、DELETE根据 Content-Type生成browserable的交互页面(自动为API生成非常友好的浏览器页面)非常细粒度的权限管理(可以细粒度到field级别)示意图安装$pipinstalldjangorestframew......