GO-ZERO
01基础001快速入门
01基础002配置文件
01基础003web开发一
01基础004web开发二
本文档使用 MrDoc 发布
-
+
首页
01基础004web开发二
## 1. 跨域 跨域是浏览器基于同源策略的一种安全手段。 同源: 协议相同(protocol) 主机相同(host) 端口相同(port) 当访问不是同源的服务地址时,就会发生跨域问题 " ### 1.1 go-zero跨域配置 第一种 ``` server := rest.MustNewServer(c.RestConf, rest.WithCors("http://localhost:5173")) ``` 第二种 在有些情况下,我们需要传递一些自定义的header,这时候仍旧会出现跨域问题 所以我们需要自定义跨域的header ``` server := rest.MustNewServer(c.RestConf, rest.WithCorsHeaders("xxxx"), ) ``` 第三种 如果我们既想要自定义header,又想要控制跨域的域名 ``` server := rest.MustNewServer(c.RestConf, //顺序不能颠倒 rest.WithCors("http://localhost:5173"), rest.WithCorsHeaders("xxxx"), ) ``` 第四种 如果想要自定义跨域 ``` server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(func(header http.Header) { var allowOrigin = "Access-Control-Allow-Origin" var allOrigins = "http://localhost:5173" var allowMethods = "Access-Control-Allow-Methods" var allowHeaders = "Access-Control-Allow-Headers" var exposeHeaders = "Access-Control-Expose-Headers" var methods = "GET, HEAD, POST, PATCH, PUT, DELETE, OPTIONS" var allowHeadersVal = "xxxx, Content-Type, Origin, X-CSRF-Token, Authorization, AccessToken, Token, Range" var exposeHeadersVal = "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers" var maxAgeHeader = "Access-Control-Max-Age" var maxAgeHeaderVal = "86400" header.Set(allowOrigin, allOrigins) header.Set(allowMethods, methods) header.Set(allowHeaders, allowHeadersVal) header.Set(exposeHeaders, exposeHeadersVal) header.Set(maxAgeHeader, maxAgeHeaderVal) }, func(w http.ResponseWriter) { }), ) ``` ## 2. 请求参数 ### 2.1 form表单 ``` type Request struct { Name string `form:"name"` // 必填参数 Age int `form:"age,optional"` // optional定义非必填参数 } var req Request err := httpx.Parse(r, &req) // 解析参数 #2.2 json type Request struct { Name string `json:"name"` Age int `json:"age"` } var req Request err := httpx.Parse(r, &req) // 解析参数 #2.3 path type Request struct { Name string `path:"name"` } // Path定义 rest.Route{ Method: http.MethodGet, Path: "/user/:name", Handler: handle, } var req Request err := httpx.Parse(r, &req) // 解析参数 `` #2.4 header参数 type Request struct { Authorization string `header:"authorization"` } var req Request err := httpx.Parse(r, &req) // 解析参数 #2.5 参数默认值 type Request struct { Age int `form:"age,default=18"` } var req Request err := httpx.Parse(r, &req) // 解析参数 #2.6 参数枚举值 type Request struct { Age int `form:"age,options=18|19"` } var req Request err := httpx.Parse(r, &req) // 解析参数 #2.7 参数区间定义 type Request struct { Age int `form:"age,range=[18:35)"` } var req Request err := httpx.Parse(r, &req) // 解析参数 ``` ## 3. 中间件 ### 3.1 内置中间件 鉴权管理中间件 AuthorizeHandler 熔断中间件 BreakerHandler 内容安全中间件 ContentSecurityHandler 解密中间件 CryptionHandler 压缩管理中间件 GunzipHandler 日志中间件 LogHandler ContentLength 管理中间件 MaxBytesHandler 限流中间件 MaxConnsHandler 指标统计中间件 MetricHandler 普罗米修斯指标中间件 PrometheusHandler panic 恢复中间件 RecoverHandler 负载监控中间件 SheddingHandler 超时中间件 TimeoutHandler 链路追踪中间件 TraceHandler ``` type MiddlewaresConf struct { Trace bool `json:",default=true"` Log bool `json:",default=true"` Prometheus bool `json:",default=true"` MaxConns bool `json:",default=true"` Breaker bool `json:",default=true"` Shedding bool `json:",default=true"` Timeout bool `json:",default=true"` Recover bool `json:",default=true"` Metrics bool `json:",default=true"` MaxBytes bool `json:",default=true"` Gunzip bool `json:",default=true"` } ``` ``` Name: HelloWorld.api Host: 127.0.0.1 Port: 8080 Middlewares: Metrics: false ``` ### 3.2 自定义中间件 ``` server := rest.MustNewServer(rest.RestConf{}) defer server.Stop() server.Use(middleware) // 自定义的中间件 func middleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { w.Header().Add("X-Middleware", "static-middleware") next(w, r) } } ``` ## 4. redis集成 ### 4.1 docker-compose部署配置 version: '3.3' services: redis: container_name: zero-redis-node image: redis:latest restart: always ports: - "6379:6379" volumes: - ./volume/redis/dаta:/root/redis environment: - REDIS_PASSWORD=mszlu - REDIS_PORT=6379 - REDIS_DATABASES=16 redis-cluster-master: image: redis:latest container_name: redis-cluster-master restart: always command: redis-server --port 7000 --requirepass mszlu --appendonly yes ports: - 7000:7000 volumes: - ./volume/redis-cluster/data:/data networks: - redis-cluster redis-cluster-slave1: image: redis:latest container_name: redis-slave-1 restart: always command: redis-server --slaveof redis-cluster-master 7000 --port 7001 --requirepass mszlu --masterauth mszlu --appendonly yes ports: - 7001:7001 depends_on: - master volumes: - ./volume/redis-cluster/data:/data networks: - redis-cluster networks: redis-cluster: #4.2 单节点 go-zero内置配置: RedisConf struct { Host string Type string `json:",default=node,options=node|cluster"` Pass string `json:",optional"` Tls bool `json:",optional"` NonBlock bool `json:",default=true"` // PingTimeout is the timeout for ping redis. PingTimeout time.Duration `json:",default=1s"` } Host:Redis 服务地址 ip:port, 如果是 Redis Cluster 则为 ip1:port1,ip2:port2,ip3:port3 Type:node 单节点 Redis ,cluster Redis 集群 Pass:认证密码 Tls:是否开启tls NonBlock:是否以非阻塞模式启动 PingTimeout:ping超时时间,用于检测redis是否连接成功 go get github.com/redis/go-redis/v9 RedisConfig: Host: "127.0.0.1:6379" Pass: "mszlu" Type: "node" Tls: false NonBlock: false PingTimeout: 1s package db import "github.com/zeromicro/go-zero/core/stores/redis" func NewRedis(conf redis.RedisConf) *redis.Redis { return redis.MustNewRedis(conf) } servicecontext中注入: package svc import ( "github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/sqlx" "user-api/internal/config" "user-api/internal/db" ) type ServiceContext struct { Config config.Config Conn sqlx.SqlConn RedisClient *redis.Redis } func NewServiceContext(c config.Config) *ServiceContext { sqlConn := db.NewMysql(c.MysqlConfig) redisClient := db.NewRedis(c.RedisConfig) return &ServiceContext{ Config: c, Conn: sqlConn, RedisClient: redisClient, } } 改造登录代码: func (l *LoginLogic) Login(req *types.LoginReq) (resp *types.LoginResp, err error) { // todo: add your logic here and delete this line userModel := user.NewUserModel(l.svcCtx.Conn) u, err := userModel.FindByUsernameAndPwd(l.ctx, req.Username, req.Password) if err != nil { l.Logger.Error(err) return nil, biz.DBError } if u == nil { return nil, biz.NameOrPwdError } //登录成功 生成token secret := l.svcCtx.Config.Auth.Secret expire := l.svcCtx.Config.Auth.Expire token, err := biz.GetJwtToken(secret, time.Now().Unix(), expire, u.Id) if err != nil { l.Logger.Error(err) return nil, biz.TokenError } //把token存入redis err = l.svcCtx.RedisClient.SetexCtx(context.Background(), "token:"+token, strconv.FormatInt(u.Id, 10), int(expire)) if err != nil { return nil, biz.RedisError } resp = &types.LoginResp{ Token: token, } return } 测试 ## 4.3 集群 集群方式只需要改配置即可,go-zero对集群和单机做了适配。 go-zero内置redis的缺陷: 不能选择redis数据库 不能配置连接池 对原生go-redis配置项不能自定义 实际开发中,如果对配置项需要精细化控制,建议直接使用go-redis库即可,并且自行对go-redis进行封装
admin
2025年1月9日 14:00
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码