• sqler sql 转rest api 源码解析(三) rest协议


    rest 服务说明

    rest 协议主要是将配置文件中的宏暴露为rest 接口,使用了labstack/echo web 框架,同时基于context 模型
    进行宏管理对象的共享,同时进行了一些中间件的注册 cors RemoveTrailingSlash gzip Recover

    rest 启动

    • 中间件注册
     
      e.Pre(middleware.RemoveTrailingSlash())
      e.Use(middleware.CORS())
      e.Use(middleware.GzipWithConfig(middleware.GzipConfig{Level: 9}))
      e.Use(middleware.Recover())
    • 路由配置
      默认配置,以及指定宏的路由
     
      e.GET("/", routeIndex)
      e.Any("/:macro", routeExecMacro, middlewareAuthorize)
     
     
    • 宏执行路由
      包含了一个授权的中间件,同时在这个中间件中传递共享变量(macro)
     
    func middlewareAuthorize(next echo.HandlerFunc) echo.HandlerFunc {
      return func(c echo.Context) error {
        if strings.HasPrefix(c.Param("macro"), "_") {
          return c.JSON(403, map[string]interface{}{
            "success": false,
            "error": "access not allowed",
          })
        }
        macro := macrosManager.Get(c.Param("macro"))
        if macro == nil {
          return c.JSON(404, map[string]interface{}{
            "success": false,
            "error": "resource not found",
          })
        }
        if len(macro.Methods) < 1 {
          macro.Methods = []string{c.Request().Method}
        }
        methodIsAllowed := false
        for _, method := range macro.Methods {
          method = strings.ToUpper(method)
          if c.Request().Method == method {
            methodIsAllowed = true
            break
          }
        }
        if !methodIsAllowed {
          return c.JSON(405, map[string]interface{}{
            "success": false,
            "error": "method not allowed",
          })
        }
        // for _, endpoint := range macro.Authorizers {
        // parts := strings.SplitN(endpoint, " ", 2)
        // if len(parts) < 2 {
        // return c.JSON(500, map[string]interface{}{
        // "success": false,
        // "error": fmt.Sprintf("authorizer: %s is invalid", endpoint),
        // })
        // }
        // resp, err := resty.R().SetHeaders(map[string]string{
        // "Authorization": c.Request().Header.Get("Authorization"),
        // }).Execute(parts[0], parts[1])
        // if err != nil {
        // return c.JSON(500, map[string]interface{}{
        // "success": false,
        // "error": err.Error(),
        // })
        // }
        // if resp.StatusCode() >= 400 {
        // return c.JSON(resp.StatusCode(), map[string]interface{}{
        // "success": false,
        // "error": resp.Status(),
        // })
        // }
        // }
       // 路由共享变量
        c.Set("macro", macro)
        return next(c)
      }
    }
     
     
    • routeExecMacro
      routes.go 解析请求参数,解析宏,返回json 格式数据
     
    // routeExecMacro - execute the requested macro
    func routeExecMacro(c echo.Context) error {
    // 获取请求参数,转换为支持宏绑定的map 对象
      macro := c.Get("macro").(*Macro)
      input := make(map[string]interface{})
      body := make(map[string]interface{})
      c.Bind(&body)
      for k := range c.QueryParams() {
        input[k] = c.QueryParam(k)
      }
      for k, v := range body {
        input[k] = v
      }
      headers := c.Request().Header
      for k, v := range headers {
        input["http_"+strings.Replace(strings.ToLower(k), "-", "_", -1)] = v[0]
      }
      out, err := macro.Call(input)
      if err != nil {
        code := errStatusCodeMap[err]
        if code < 1 {
          code = 500
        }
        return c.JSON(code, map[string]interface{}{
          "success": false,
          "error": err.Error(),
          "data": out,
        })
      }
      return c.JSON(200, map[string]interface{}{
        "success": true,
        "data": out,
      })
    }
     
     

    参考资料

    https://github.com/labstack/echo
    https://github.com/alash3al/sqler/blob/master/server_rest.go
    https://github.com/alash3al/sqler/blob/master/routes.go

  • 相关阅读:
    Ansible学习 Playbooks_1
    Ansible学习 ad-hoc命令
    Ansible学习 Patterns
    【转】对于SQL SERVER 事务日志已满问题整理
    【转】Apache配置正向代理与反向代理
    【转】Python的IDE和破解Code——pycharm
    【转】SQLServer 数据库变成单个用户后无法访问问题的解决方法
    【转】 尝试在数据库5 中提取逻辑页() 失败。该逻辑页属于分配单元xxx而非xxx
    【Oracle】Oracle版本导入导出问题
    【Java】eclipse导入war包二次开发
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/10268109.html
Copyright © 2020-2023  润新知