• No labels

14 Comments

  1. ACL 这块后续有无考虑内置类似功能?

    1. 权限控制未来会通过社区模块的形式提供,不过目前暂无工作规划,欢迎大家贡献。

  2. 洋葱图上是不是应该加两个middleware描述.分别是在路由外层的global.Middleware及路由内层group.Middleware.

  3. 当客户端使用POST请求,并且有携带文件上传,比如

    curl --location --request POST 'http://127.0.0.1:8080/api/tasks' --form 'file=@"/Users/test/Downloads/test.pdf"'

    路由代码

    func MiddlewareAuth(r *ghttp.Request) {
    	r.Response.ClearBuffer()
    	r.Response.WriteStatusExit(401,"哎哟我去,服务器居然开小差了,请稍后再试吧!")
    }
    
    func init() {
    	s := g.Server()
    	s.Group("/api", func(group *ghttp.RouterGroup) {
    		group.Middleware(MiddlewareAuth)
    		group.POST("/tasks", api.Task.Create)
    	})
    }


    此时curl会返回 HTTP error before end of send, stop sending 错误

    并且postman也是无法正常显示,提示错误

    Could not get response,Error: write EPIPE




  4. 请问一下,现在我有多个中间件,如果前面的中间件需要抛出一个错误,后面的中间件能拦截到吗?

    1. 可以的,后面的中间件通过r.GetError可以获取前面的产生错误或者异常,中间件中也可以通过r.SetError来设置自定义的错误。

  5. 拦截静态文件请求该如何实现?

    1. 静态资源使用HOOK

  6. 郭强 中间件设置了httpStatus之后,为何response自动加上了 http 状态码的描述呢?

    func (s *sMiddleware) ResponseHandler(r *ghttp.Request) {
    	r.Middleware.Next()
    
    	r.Response.Header().Set("Content-Type", "application/json;charset=utf-8")
    
    	// 如果已经有返回内容,那么该中间件什么也不做
    	if r.Response.BufferLength() > 0 {
    		return
    	}
    
    	var (
    		err  error
    		res  interface{}
    		code gcode.Code = gcode.CodeOK
    	)
    	res, err = r.GetHandlerResponse()
    	if err != nil {
    
    		code = gerror.Code(err)
    		if code == errorCode.CodeNil {
    			code = errorCode.CodeInternalError
    		}
    		if detail, ok := code.Detail().(errorCode.MyCodeDetail); ok {
    			r.Response.WriteStatus(detail.HttpCode)  // 此处是 404
    		}
    		response.JsonExit(r, code.Code(), err.Error())    // 此处code=65;Message="用户 uuid=1 不存在。";Data={}
    	} else {
    		response.JsonExit(r, code.Code(), "", res)
    	}
    }

    发起请求:curl -X 'GET' 'http://127.0.0.1:8199/user/1' -H 'accept: application/json' ,得到的response如下:

    Not Found{"code":65,"message":"用户 uuid=1 不存在。","data":{}}

    为什么多了 Not Found? 怎么去掉

    1. r.Response.WriteStatus(detail.HttpCode 会往response 写数据

      // WriteStatus writes HTTP `status` and `content` to the response.
      // Note that do not set Content-Type header here.
      func (r *Response) WriteStatus(status int, content ...interface{}) {
      	r.WriteHeader(status)
      	if len(content) > 0 {
      		r.Write(content...)
      	} else {
      		r.Write(http.StatusText(status))  // 此处会写入404对应的字符串
      	}
      }

      所以多了一个 response 会多了一个 “Not Found”

      只需要在写入Status之后,把response 清空一下即可,完整代码如下:

      // 返回处理中间件
      func (s *sMiddleware) ResponseHandler(r *ghttp.Request) {
      	r.Middleware.Next()
      
      	// 如果已经有返回内容,那么该中间件什么也不做
      	if r.Response.BufferLength() > 0 {
      		return
      	}
      
      	var (
      		err  error
      		res  interface{}
      		code gcode.Code = gcode.CodeOK
      	)
      	res, err = r.GetHandlerResponse()
      	if err != nil {
      
      		code = gerror.Code(err)
      		if code == errorCode.CodeNil {
      			code = errorCode.CodeInternalError
      		}
      		// TODO: 修改http 状态码出问题
      		if detail, ok := code.Detail().(errorCode.MyCodeDetail); ok {
      			r.Response.WriteStatus(detail.HttpCode)
      			r.Response.ClearBuffer() // gf 会自动往response追加http.StatusText。此处不需要,所以删除掉。
      		}
      		response.JsonExit(r, code.Code(), err.Error())
      	} else {
      		response.JsonExit(r, code.Code(), "", res)
      	}
      }


      )

    2. 你有没有想过是你的问题呢?设置状态码不应该是改Header吗。你应该调用

      r.WriteHeader(status)

      就可以了。无需调用WriteStatus这个本来就是向浏览器输出状态内容的。你直接改header就可以了

  7. 郭强 middleware貌似不能return error。如文档上提到的同时存在MiddlewareAuth, MiddlewareErrorHandler,

    group.Middleware(MiddlewareAuth, MiddlewareErrorHandler)

    期望MiddlewareAuth校验失败,不再继续执行后续的业务功能代码,能否在MiddlewareAuth return error,然后在MiddlewareErrorHandler统一处理呢?

  8. 请问如何支持标准库的 http Handler 作为中间件使用?

    郭强 

    支持这样的操作吗?因为很多时候可能需要直接使用标准库的 http.Handler

  9. 在中间件里可以修改HandlerResponse吗?