跟着b站https://space.bilibili.com/361469957 杨旭老师学习做的笔记

中间件

什么是中间件

请求————> 中间件 ————> 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)
}
)
}

go web学习(四)的更多相关文章

  1. java web 学习四(http协议)

    一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...

  2. Java Web 学习路线

    实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...

  3. web—第四章css&第五章

     web—第四章css&第五章 终于迎接等待已久的CSS,在没学这个之前,我们只会用一点img,查一点小图片,或者是用style改一下颜色,而且比较麻烦.现在多了个css在文件夹在创建一个cs ...

  4. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  5. Java Web学习系列——Maven Web项目中集成使用Spring

    参考Java Web学习系列——创建基于Maven的Web项目一文,创建一个名为LockMIS的Maven Web项目. 添加依赖Jar包 推荐在http://mvnrepository.com/.h ...

  6. Java Web(十四) 编写MyBookStore项目的总结

    这几天一直没有发博文,原因是在写一个书城的小项目,作为web学习的最后沉淀,接下来就要到框架的学习了. --WH 一.项目介绍 从网上找的一个培训机构的小项目,名称叫做 书城购物网站 吧,其中就是分前 ...

  7. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

  8. Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档

    0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...

  9. Java反射:Web学习的灵魂

    反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...

  10. Web学习之css

    CSS指层叠样式表(Cascading Style Sheets),CSS 是标准的布局语言,用来控制元素的尺寸.颜色.排版.CSS 由 W3C 发明,用来取代基于表格的布局.框架以及其他非标准的表现 ...

随机推荐

  1. post-css/less/sass样式嵌套与命令之"&"符号—BEM

    看了< less 的 & 详解 https://www.jianshu.com/p/127b0974cfc3>,对于此文再做一别补充 常见用法: 直接嵌套写法 .a{   colo ...

  2. golang常用库包:log日志记录-uber的Go日志库zap使用详解

    Go 日志记录库:uber-go 的日志操作库 zap 使用 一.简介 zap 是 uber 开源的一个高性能,结构化,分级记录的日志记录包. go1.20.2 zap v1.24.0 zap的特性 ...

  3. day48:django前戏:HTTP协议&自定义web框架

    目录 1.HTTP协议 1.HTTP协议简介 2.HTTP协议概述 3.HTTP协议工作原理 4.HTTP协议请求方法 5.HTTP协议状态码 6.URL 7.HTTP请求格式 8.HTTP响应格式 ...

  4. php 正则去掉<p>&nbsp;</p> 空格 &nbsp;

    $str=' <p> </p><p> </p><p> </p><p> </p><p>< ...

  5. nginx概要

    新机(CentOS7)配置nginx: 一. 更新yum源为阿里云镜像 ping mirrors.aliyun.com mv /etc/yum.repos.d/CentOS-Base.repo /et ...

  6. 【LeetCode动态规划#14】子序列系列题(最长递增子序列、最长连续递增序列、最长重复子数组、最长公共子序列)

    最长递增子序列 力扣题目链接(opens new window) 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其 ...

  7. Tarjan学习笔寄

    tarjan算法 参考博客: https://www.cnblogs.com/nullzx/p/7968110.html https://www.cnblogs.com/ljy-endl/p/1156 ...

  8. 【必知必会的MySQL知识】①初探MySQL

    目录 前言 MySQL是什么? MySQL版本 表的概念 表中的列和数据类型 行 主键 什么是SQL 实践操作 小结 前言 周所周知MySQL已成为全世界最受欢迎的数据库之一.无论你用的何种编程语言在 ...

  9. 在算数运算中,能否将 bool 值 true 视作 1?

    true == 1; true + 1; If the destination type is bool, see 4.12. If the source type is bool, the valu ...

  10. 记一道国际赛CTF web题

    这是一篇关于打d3ctf坐牢,无奈去打国际赛的题解. TAMUCTF [Blackbox] 首先打开页面,然后发现一个登陆框 刚开始最先想到就是弱口令登陆,尝试几个后发现登陆不进去. 之后我就换了一个 ...