• Echo框架


    Echo框架

    1.请求参数的获取

    (1.)路径参数获取

    e.GET("/users/:id", getUser)
    
    id := c.Param("id")
    

    (2.)查询参数获取

    /show?team=x-men&member=wolverine 
      
    team := c.QueryParam("team")
    member := c.QueryParam("member")
    

    (3.)Form表单元素获取

    name := c.FormValue("name")
    avatar, err := c.FormFile("avatar")
    

    (4.) JSON请求绑定

    type User struct {
    	Name  string `json:"name" xml:"name" form:"name" query:"name"`
    	Email string `json:"email" xml:"email" form:"email" query:"email"`
    }
    
    e.POST("/users", func(c echo.Context) error {
    	u := new(User)
        //调用echo.Context的Bind函数将请求参数和User对象进行绑定。
    	if err := c.Bind(u); err != nil {
    		return err
    	}
        //请求参数绑定成功后 u 对象就保存了请求参数。
        //这里直接将请求参数以json格式显示
        //注意:User结构体,字段标签定义中,json定义的字段名,就是User对象转换成json格式对应的字段名。
    	return c.JSON(http.StatusCreated, u)
    })
    

    2.响应返回

    (1.)字符串返回
    c.String语法:
    c.String(http状态码,"字符串内容")

    c.String(http.StatusOK, "xxx")
    

    (2.) JSON方式返回
    c.JSON语法:
    c.JSON(http状态码, 结构体变量)

    // 通过json标签定义struct字段转换成json字段的名字。
    type User struct {
        ID int `json:"id"`
        Name string `json:"name"`
    }
    
    u := User{2, "zhangsan"}
    c.JSON(http.StatusOK, u) //返回结果:{"id":2,"username":"zhangsan"}
    
    //格式化json输出
    c.JSONPretty(http.StatusOK, u, "  ")
    
    // 也可以用json stream方式,不推荐
    json.NewEncoder(c.Response()).Encode(u)
    
    //外部json
    encodedJSON := []byte{} // Encoded JSON from external source
    return c.JSONBlob(http.StatusOK, encodedJSON)
    

    (3.)HTML方式返回
    c.HTML语法:
    c.HTML(http状态码, "html内容")

    c.HTML(http.StatusOK, html)
    

    (4.)通过文件格式响应
    方式一:
    // 通过File函数,直接返回本地文件,参数为本地文件地址。
    // 函数说明:c.File("文件路径")

     c.File("/var/www/1.jpg")
    

    方式二:
    //通过Attachment函数,返回本地文件,类似File函数,区别是可以指定下载的文件名。
    //函数说明: c.Attachment("文件路径", "下载的文件名")

    c.Attachment("/var/www/1.jpg", "1.jpg")
    

    方式三:
    //通过Blob函数,以二进制数据格式返回文件
    //函数说明:c.Blob(状态码, "contentType", byte数组)

    data := []byte(`0306703,0035866,NO_ACTION,06/19/20060086003,"0005866",UPDATED,06/19/2006`)
    c.Blob(http.StatusOK, "text/csv", data)
    

    方式四:
    //通过Stream函数,以stream流的方式返回文件
    //函数说明:
    //Stream(code int, contentType string, r io.Reader) error
    //参数说明:
    // code - 状态码
    // contentType - html内容类型
    // r - 实现io.Reader接口的struct对象都可以直接输出内容

     //打开文件
    f, err := os.Open("/var/www/1.jpg")
    c.Stream(http.StatusOK, "image/png", f)
    

    (5.)设置响应头

     c.Response().Header().Add("name", "zhangsan")
    

    3.静态资源展示

    (1.)静态资源的展示

    e := echo.New()
    // 设置 /static 为静态资源url的前缀,当前程序运行目录下面的static目录为静态资源目录
    e.Static("/static", "static")
    
    //访问 / 就是访问public/index.html文件, index.html相当于站点默认首页
    e.File("/", "public/index.html")
    

    (2.)URL的显示

    静态url路径 : /users/center
    带路径参数的url路径 : /user/:id
    带星号(*)模糊匹配参数的url路径 : /foods/*  
    
    //匹配任意路径
    Echo.Any(path string, h Handler)
    //匹配指定方法的路径
    Echo.Match(methods []string, path string, h Handler)
    

    (3.)控制器函数
    控制器函数接受一个上下文参数,并返回一个错误。可以通过上下文参数,获取http请求参数,响应http请求。

    func HandlerFunc(c echo.Context) error
    

    (4.)路由分组

    g := e.Group("/admin")
    g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
    	if username == "joe" && password == "secret" {
    		return true, nil
    	}
    	return false, nil
    }))
    

    (5.)路由命名
    每一个路由注册方法都会返回一个路由对象,可以给这个路由对象起个名

    route := e.POST("/users", func(c echo.Context) error {
    })
    route.Name = "create-user"
    
    // or using the inline syntax
    e.GET("/users/:id", func(c echo.Context) error {
    }).Name = "get-user"
    

    (6.)列出所有路由信息

    // Routes
    e.POST("/users", createUser)
    e.GET("/users", findUser)
    
    
    // 获取所有的路由信息
    data, _ := json.MarshalIndent(e.Routes(), "", "  ")
    
    // 将路由信息写入到json文件
    ioutil.WriteFile("routes.json", data, 0644)
    
    //routes.json 输出结果如下
    [
      {
        "method": "POST",
        "path": "/users",
        "name": "main.createUser"
      },
      {
        "method": "GET",
        "path": "/users",
        "name": "main.findUser"
      },
    ]
    

    4.Cookie的操作

    (1.)设置cookie

    // 初始化cookie对象
    cookie := new(http.Cookie)
    cookie.Name = "xxx-domain"
    cookie.Value = "xxx.com"
    cookie.Path = "/"
    // cookie有效期为3600秒
    cookie.MaxAge = 3600
    
    // 设置cookie
    c.SetCookie(cookie)
    

    (2.)获取cookie

    // 根据cookie名,获取cookie, cookie存在则返回http.Cookie结构体
    cookie, err := c.Cookie("xxx-domain")
    
    //打印cookie名
    fmt.Println(cookie.Name)
    //打印cookie值
    fmt.Println(cookie.Value)
    

    (3.)删除cookie

    // 初始化cookie对象
    cookie := new(http.Cookie)
    // 删除cookie只需要设置cookie名字就可以
    cookie.Name = "xxx-domain"
    //cookie有效期为-1秒,注意这里不能设置为0,否则不会删除cookie
    cookie.MaxAge = -1
    
    //设置cookie
    c.SetCookie(cookie)
    

    5.Session处理

    (1.)导入对应的包

      "github.com/gorilla/sessions"
      "github.com/labstack/echo-contrib/session"
    

    (2.)设置session中间件

    //初始化echo实例
    e := echo.New()
    
    //设置session数据保存目录
    sessionPath := "./session_data"
    
    //设置cookie加密秘钥, 可以随意设置
    sessionKey = "Onxuh20a2ihhh2"
    
    //设置session中间件
    //这里使用的session中间件,session数据保存在指定的目录
    e.Use(session.Middleware(sessions.NewFilesystemStore(sessionPath, []byte(sessionKey))))
    

    (3.)读写session数据
    a.用户登录并记录会话数据

    e.POST("/login", func(c echo.Context) error {
        //获取登录请求参数
        username := c.FormValue("username")
        password := c.FormValue("password")
    	
    	//校验帐号密码是否正确	
        if username == "tizi365" && password == "123456" {
    		//密码正确, 下面开始注册用户会话数据
    		//以user_session作为会话名字,获取一个session对象
    		sess, _ := session.Get("user_session", c)
    		
    		//设置会话参数
    		sess.Options = &sessions.Options{
                Path:     "/",  //所有页面都可以访问会话数据
                MaxAge:   86400 * 7,   //会话有效期,单位秒
            }
            
            //记录会话数据, sess.Values 是map类型,可以记录多个会话数据
            sess.Values["id"] = username
            sess.Values["isLogin"] = true
            
            //保存用户会话数据
            sess.Save(c.Request(), c.Response())
            
    		return c.String(200, "登录成功!")
    	} else {
    		return c.String(200, "密码不正确!")
    	}
    })
    

    b.登录成功后,可以通过下面的方式读取用户会话数据

    e.POST("/home", func(c echo.Context) error {
        //以user_session作为会话名字,获取一个session对象
        //注意这里的session名字,必须跟登录注册的会话名字一致
    	sess, _ := session.Get("user_session", c)
    	
    	//通过sess.Values读取会话数据
    	username := sess.Values["id"]
    	isLogin  := sess.Values["isLogin"]
    	
    	//打印会话数据
    	fmt.Println(username)
    	fmt.Println(isLogin)
    })
    

    5.上传文件

    func upload(c echo.Context) error {
    	// 通过FormFile函数获取客户端上传的文件
    	file, _ := c.FormFile("file")
    	
    	//打开用户上传的文件
    	src, _ := file.Open()
    	defer src.Close()
    
    	// 创建目标文件,就是我们打算把用户上传的文件保存到什么地方
    	// file.Filename 参数指的是我们以用户上传的文件名,作为目标文件名,也就是服务端保存的文件名跟用户上传的文件名一样
    	dst, _ := os.Create(file.Filename)
    	
    	defer dst.Close()
    
    	// 这里将用户上传的文件复制到服务端的目标文件
        io.Copy(dst, src)
    
    	return c.HTML(http.StatusOK, fmt.Sprintf("<p>文件上传成功: %s</p>", file.Filename))
    }
    

    6.中间件

    (1.)重定向机制

    // http强制跳转至https
    e := echo.New()
    e.Pre(middleware.HTTPSRedirect()) //路由之前执行
    
    // www跳转,访问 http://xxx.com  --> http://www.xxx.com
    e.Pre(middleware.WWWRedirect())
    
    //https+www跳转 http://xxx.com  --> https://www.xxx.com
    e.Pre(middleware.HTTPSWWWRedirect())
    
    // Rewrite 用于将一个url重定向到另外一个url。
    // "*"星代表任意字符串,$1 代表引用表达式中第一个星(*)的匹配值, $2代表第二个,以此类推。
    e.Pre(middleware.Rewrite(map[string]string{
      "/old":              "/new",   //将/old重定向至/new
      "/api/*":            "/$1",    
      "/js/*":             "/public/javascripts/$1",
      "/users/*/orders/*": "/user/$1/order/$2",
    }))
    

    (2.)Recover中间件
    主要用于拦截panic错误并且在控制台打印错误日志,避免echo程序直接崩溃。

    //初始化echo实例
    e := echo.New()
    
    //注册中间件
    e.Use(middleware.Recover())
    

    (3.)日志中间件
    Logger中间件主要用于打印http请求日志。

    //初始化echo实例
    e := echo.New()
    
    //注册中间件
    e.Use(middleware.Logger())
    

    (4.)自定义中间件

    // 初始化echo实例
    e := echo.New()
    // 注册中间件
    e.Use(Count)
    
    //记录访问量
    var totalRequests  = 0
    //中间件函数
    func Count(next echo.HandlerFunc) echo.HandlerFunc {
    	return func(c echo.Context) error {
    		//在这里处理拦截请求的逻辑
    		//累计访问量
    		totalRequests++
    		
    		//在响应头中输出访问量
    		c.Response().Header().Add("requests", fmt.Sprintf("%d", totalRequests))
    
    		//执行下一个中间件或者执行控制器函数, 然后返回执行结果
    		return next(c)
    	}
    }
    

    (5.)跳过中间件

    e := echo.New()
    e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    	Skipper: func(c echo.Context) bool {
    		if strings.HasPrefix(c.Request().Host, "localhost") {
    			return true
    		}
    		return false
    	},
    }))
    

    (6.)鉴权中间件

    e.Use(middleware.BasicAuthWithConfig(middleware.BasicAuthConfig{}))
    // 默认配置
    DefaultBasicAuthConfig = BasicAuthConfig{
    	Skipper: DefaultSkipper,
    }
    

    (7.)请求和响应的拦截

    e.Use(middleware.BodyDump(func(c echo.Context, reqBody, resBody []byte) {
    }))
    

    (8.)最大请求限制

    e.Use(middleware.BodyLimit("2M"))
    

    (9.)Casbin权限控制

    enforcer, err := casbin.NewEnforcer("casbin_auth_model.conf", "casbin_auth_policy.csv")
    e.Use(casbin_mw.Middleware(enforcer))
    

    (10.)跨域访问的中间件

    e := echo.New()
    e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
      AllowOrigins: []string{"https://labstack.com", "https://labstack.net"},
      AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept},
     AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete},
    }))
    

    (11.)路由追踪中间件

    package main
    import (
        "github.com/labstack/echo-contrib/jaegertracing"
        "github.com/labstack/echo/v4"
        "net/http"
        "time"
    )
    func main() {
        e := echo.New()
        // Enable tracing middleware
        c := jaegertracing.New(e, nil)
        defer c.Close()
        e.GET("/", func(c echo.Context) error {
            // Wrap slowFunc on a new span to trace it's execution passing the function arguments
    		jaegertracing.TraceFunction(c, slowFunc, "Test String")
            return c.String(http.StatusOK, "Hello, World!")
        })
        e.Logger.Fatal(e.Start(":1323"))
    }
    
    // A function to be wrapped. No need to change it's arguments due to tracing
    func slowFunc(s string) {
    	time.Sleep(200 * time.Millisecond)
    	return
    }
    

    7.错误处理

    (1.)返回http错误

    //日志记录
    c.Logger().Error(err)
    //返回错误
    echo.NewHTTPError(http.StatusUnauthorized, "Please provide valid credentials")
    

    8.入参校验

    package main
    
    import (
    	"github.com/go-playground/validator"
    	"github.com/labstack/echo/v4"
    	"net/http"
    )
    
    type (
    	User struct {
    		Name  string `json:"name" validate:"required"`
    		Email string `json:"email" validate:"required,email"`
    	}
    
    	CustomValidator struct {
    		validator *validator.Validate
    	}
    )
    
    func (cv *CustomValidator) Validate(i interface{}) error {
    	return cv.validator.Struct(i)
    }
    
    func main() {
    	e := echo.New()
    	e.Validator = &CustomValidator{validator: validator.New()}
    	e.POST("/users", func(c echo.Context) (err error) {
    		u := new(User)
    		if err = c.Bind(u); err != nil {
    			return
    		}
    		if err = c.Validate(u); err != nil {
    			return
    		}
    		return c.JSON(http.StatusOK, u)
    	})
    	e.Logger.Fatal(e.Start(":1323"))
    }
    

    8.Echo框架添加跨域访问

    e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
    		AllowOrigins: []string{"*"},
    		AllowHeaders: []string{"X-Requested-With", "Content-Type", "Origin", "Authorization", "Accept", "Client-Security-Token", "Accept-Encoding"},
    		AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE},
    	}))
    

    9.echo文件下载

    // 读取文件内容
    fileData, _ := ioutil.ReadFile(uploadPath)
    // 获取文件名
    fileName := path.Base(uploadPath)
    // 防止中文乱码
    fileName = url.QueryEscape(fileName) 
    // 将文件名返回到响应头中
    c.Response().Header().Set(echo.HeaderContentDisposition, "attachment; filename="+fileName)
    返回文件流
    return c.Stream(http.StatusOK, echo.MIMEOctetStream, bytes.NewReader(fileData))
    

    相关链接

    https://www.tizi365.com/archives/73.html
    https://echo.labstack.com/guide/context

  • 相关阅读:
    ArcGIS Server 服务迁移、恢复
    发布(高程数据)服务,Service Editor界面无LERC格式选项
    汇总10.4版本ArcGIS Server与ArcMap 安装+SDE+注册数据源(非破解)
    ArcGIS Server 缓存服务增加新比例尺缓存
    ArcMap 标注、注记、图形文本
    ArcGIS Server 缓存服务切图范围
    Oracle 安装 INS-30131错误。
    JAVA经典算法40题(供面试所用)
    Java 之HashMap.values()方法误用
    Java中如何把两个数组合并为一个
  • 原文地址:https://www.cnblogs.com/tomtellyou/p/12874530.html
Copyright © 2020-2023  润新知