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 发明,用来取代基于表格的布局.框架以及其他非标准的表现 ...
随机推荐
- Solon2 的通讯服务线程配置
Solon 框架,关于通讯服务的所有配置 #服务端口(默认为8080) server.port: 8080 #服务主机(ip) server.host: "0.0.0.0" #服务 ...
- day115:MoFang:种植园我的背包&种植园道具购买
目录 1.我的背包 2.道具购买 1.我的背包 1.在种植园点击背包按钮打开我的背包 在种植园打开背包,orchard.html,代码: <!DOCTYPE html> <html& ...
- MySQL(四)用户与权限管理
用户与权限管理 用户管理 MySQL用户分为普通用户和root用户,提供了许多语句来管理包括登录.退出MySQL服务器.创建用户.删除用户.密码管理和权限管理等内容. 登录MySQL服务器 mysql ...
- Midjourney 提示词工具(10 个国内外最好最推荐的)
Midjourney,是一个革命性的基于人工智能的艺术生成器,可以从被称为提示的简单文本描述中生成令人惊叹的图像.Midjourney已经迅速成为艺术家.设计师和营销人员的首选工具(包括像我这样根本不 ...
- Simulation-计算统计-随机数生成
library('ggplot2') library('dplyr') Lecture 6 Methods for generating random numbers Goal: Use U(0, 1 ...
- jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件
jdbc-plus简介 jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页.多租户等插件,可自定义扩展插件.项目地址: https://githu ...
- redhat中如何设置开机启动脚本
redhat中如何设置开机启动脚本 前面转载了一篇关于开机启动脚本的文章,觉得写的很详细了,但是自己没有实践,下面是自己实践了一种方式,来设置开机启动脚本(因为有时候我们必须开机关闭一些防火墙,SEL ...
- Python 项目:外星人入侵--第三部分
1.项目内容: 在屏幕左上角添加一个外星人,并指定合适的边框,根据第一个外星人的边距和屏幕尺寸计算屏幕上可容纳多少个外星人. 让外星人群向两边和下方移动,直到外星人被全部击落,有外星人撞到飞船,或有外 ...
- 一文讲透 RocketMQ 消费者是如何负载均衡的
RocketMQ 支持两种消息模式:集群消费( Clustering )和广播消费( Broadcasting ). 集群消费:同一 Topic 下的一条消息只会被同一消费组中的一个消费者消费.也就是 ...
- LeetCode 周赛 343(2023/04/30)结合「下一个排列」的贪心构造问题
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 大家好,我是小彭. 今天是五一假期的第二天,打周赛的人数比前一天的双周赛多了,难道大家都只玩一天吗?这场周赛 ...