go web学习(四)
跟着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学习(四)的更多相关文章
- java web 学习四(http协议)
一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...
- Java Web 学习路线
实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...
- web—第四章css&第五章
web—第四章css&第五章 终于迎接等待已久的CSS,在没学这个之前,我们只会用一点img,查一点小图片,或者是用style改一下颜色,而且比较麻烦.现在多了个css在文件夹在创建一个cs ...
- [原创]java WEB学习笔记95:Hibernate 目录
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Java Web学习系列——Maven Web项目中集成使用Spring
参考Java Web学习系列——创建基于Maven的Web项目一文,创建一个名为LockMIS的Maven Web项目. 添加依赖Jar包 推荐在http://mvnrepository.com/.h ...
- Java Web(十四) 编写MyBookStore项目的总结
这几天一直没有发博文,原因是在写一个书城的小项目,作为web学习的最后沉淀,接下来就要到框架的学习了. --WH 一.项目介绍 从网上找的一个培训机构的小项目,名称叫做 书城购物网站 吧,其中就是分前 ...
- (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合
http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...
- Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档
0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...
- Java反射:Web学习的灵魂
反射:Web学习的灵魂 我们从最初的 javac -HelloWorld.java,到面向对象部分,我们可以将Java代码在计算机中经历的阶段分为三部分:Scource源代码阶段 -- Class类对 ...
- Web学习之css
CSS指层叠样式表(Cascading Style Sheets),CSS 是标准的布局语言,用来控制元素的尺寸.颜色.排版.CSS 由 W3C 发明,用来取代基于表格的布局.框架以及其他非标准的表现 ...
随机推荐
- post-css/less/sass样式嵌套与命令之"&"符号—BEM
看了< less 的 & 详解 https://www.jianshu.com/p/127b0974cfc3>,对于此文再做一别补充 常见用法: 直接嵌套写法 .a{ colo ...
- golang常用库包:log日志记录-uber的Go日志库zap使用详解
Go 日志记录库:uber-go 的日志操作库 zap 使用 一.简介 zap 是 uber 开源的一个高性能,结构化,分级记录的日志记录包. go1.20.2 zap v1.24.0 zap的特性 ...
- day48:django前戏:HTTP协议&自定义web框架
目录 1.HTTP协议 1.HTTP协议简介 2.HTTP协议概述 3.HTTP协议工作原理 4.HTTP协议请求方法 5.HTTP协议状态码 6.URL 7.HTTP请求格式 8.HTTP响应格式 ...
- php 正则去掉<p> </p> 空格
$str=' <p> </p><p> </p><p> </p><p> </p><p>< ...
- nginx概要
新机(CentOS7)配置nginx: 一. 更新yum源为阿里云镜像 ping mirrors.aliyun.com mv /etc/yum.repos.d/CentOS-Base.repo /et ...
- 【LeetCode动态规划#14】子序列系列题(最长递增子序列、最长连续递增序列、最长重复子数组、最长公共子序列)
最长递增子序列 力扣题目链接(opens new window) 给你一个整数数组 nums ,找到其中最长严格递增子序列的长度. 子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其 ...
- Tarjan学习笔寄
tarjan算法 参考博客: https://www.cnblogs.com/nullzx/p/7968110.html https://www.cnblogs.com/ljy-endl/p/1156 ...
- 【必知必会的MySQL知识】①初探MySQL
目录 前言 MySQL是什么? MySQL版本 表的概念 表中的列和数据类型 行 主键 什么是SQL 实践操作 小结 前言 周所周知MySQL已成为全世界最受欢迎的数据库之一.无论你用的何种编程语言在 ...
- 在算数运算中,能否将 bool 值 true 视作 1?
true == 1; true + 1; If the destination type is bool, see 4.12. If the source type is bool, the valu ...
- 记一道国际赛CTF web题
这是一篇关于打d3ctf坐牢,无奈去打国际赛的题解. TAMUCTF [Blackbox] 首先打开页面,然后发现一个登陆框 刚开始最先想到就是弱口令登陆,尝试几个后发现登陆不进去. 之后我就换了一个 ...