Git Product home page Git Product logo

gear's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gear's Issues

关于 SetOnError 的回调方法

目前对于 SetOnError 的回调要求格式是func(ctx *Context, err HTTPError).

当前的预期(个人理解)是: 使用者在回调方法里处理err并调用 ctx.End 之类的方法.

存在的问题有:

  1. errParseError 处理后的对象, 使用者无法知道原始错误信息;
  2. 无法使用 ctx.Error 响应数据, 会存在死循环;

解决办法

将回调的格式改为 func(ctx *Context, err error) error:
当返回新的 error 时, gear 使用新的 error 交给 ParseError 处理, 否则还是使用原err;

这个方法并没有解决回调里调用ctx.Error导致的死循环问题.

带来的好处是: 用户可以拿到原始 error 并处理, 然后返回给 gear 继续处理;

当然, 这个方法是存在兼容问题的! 解决办法是: 回调函数支持两种方式
对于旧的方式, 再包装成新的格式.

func (ctx *Context, err error) error {
    fn(ctx, ParseError(err, ctx.Res.status()))
    return nil // 返回 nil 表示已经自行处理过
}

如果使用旧的方式, 打印一个 deprecated warning 信息.

如何注册 pprof 的路由?

您好,我正在使用您的 gear框架开发一个web应用,最近想要通过 pprof 分析应用性能方面的问题,按照 pprof 文档的指导 https://golang.org/pkg/net/http/pprof/

自定义一个 pprof 的 controller,部分代码如下:

package ctl

type Pprof struct {
	...
}

// Init ...
func (p *Pprof) Get(ctx *gear.Context) error {
	switch ctx.Param("pp") {
	default:
		pprof.Index(ctx.Res.w, ctx.Req)
	case "":
		pprof.Index(ctx.Res.w, ctx.Req)
	case "cmdline":
		pprof.Cmdline(ctx.Res.w, ctx.Req)
	case "profile":
		pprof.Profile(ctx.Res.w, ctx.Req)
	case "symbol":
		pprof.Symbol(ctx.Res.w, ctx.Req)
	}
	ctx.Res.WriteHeader(200)
}

但是查下源码发现 gear.Contexthttp.ResponseWriter不能导出,所以上面代码编译不通过。

type Response struct {
	status      int    // response Status Code
	body        []byte // the response content.
	afterHooks  []func()
	endHooks    []func()
	ended       atomicBool // indicate that app middlewares run out.
	wroteHeader atomicBool
	w           http.ResponseWriter // the origin http.ResponseWriter, should not be override.
	rw          http.ResponseWriter // maybe a http.ResponseWriter wrapper
}

请问这种情况有办法处理吗?

app.Server.serve(listener) not work

app := gear.New()
app.Use(func(ctx *gear.Context) error {
	return ctx.HTML(200, "Hello World")
})
listener, _ := net.Listen("tcp", ":9090")
app.Server.Serve(listener)

It won't response Hello World for any request.
I think add app.Server.Handler = app in New() may help. So is app.Server.ErrorLog = app.logger.

如何处理 POST 请求的 压缩数据?

现在客户端 POST 请求上来的数据是一些监控数据,因为数据量大所以采用了 zlib 压缩,如何在 gear 这边自动检测 header 并解压?

我看了 gear 关于中间件部分的文档和代码,想通过 middleware 的方式来实现,

package middleware

import (
	"compress/zlib"

	"github.com/teambition/gear"
)

// Decompress ...
func Decompress() gear.Middleware {
	return func(ctx *gear.Context) error {
		if ctx.GetHeader(gear.HeaderContentEncoding) == "deflate" {
			var err error
			ctx.Req.Body, err = zlib.NewReader(ctx.Req.Body)

			if err != nil {
				return err
			}
		}

		return nil
	}
}

app.go 注册这个中间件

app.Use(middleware.Decompress())

但是这样做好像有问题,日志报错413的错误

error:Error{Code:413, Err:\"RequestEntityTooLarge\", Msg:\"unexpected EOF\", Data:\u003cnil\u003e, Stack:\"\"}

希望您有空的时候帮忙看看我这个需求应该如何实现比较好。

[feature request] expose app.Serve(lis)

gear HTTP2 & gRPC not working for http server without TLS(or maybe the new gRPC lib related issue).

We use cmux as port proxy, so we need using app.Server.Serve(lis) to work

lis, err := net.Listen("tcp", ":8080")
if err != nil {
	log.Fatal(err)
}

// Create a cmux.
m := cmux.New(l)

// Match connections in order:
// First grpc, then HTTP, and otherwise Go RPC/TCP.
grpcL := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
_ = grpcL
httpL := m.Match(cmux.HTTP1Fast())

app := gear.New()

// etc.

// but we can not inject logger because is not exposable.
app.Server.Handler = app
app.Server.Serve(httpL)

Can we expose app.Serve(lis) func?

route with Options{TrailingSlashRedirect :false} return 421 not 404

package main

import (
"github.com/teambition/gear"
 "github.com/teambition/gear/logging"

)
func main(){
  app := gear.New()
  app.UseHandler(logging.Default(true))
  router := gear.NewRouter(gear.RouterOptions{TrailingSlashRedirect :false})
  router.Get("/hello/:name", func(ctx *gear.Context) error {
    return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
  })
  app.UseHandler(router)
  app.Error(app.Listen(":3000"))
  }
  

$curl curl http://localhost:3000/hello/gear/
127.0.0.1 - - [2021-09-10T10:35:52.391Z] "GET /hello/gear/ HTTP/1.1" 421 119 0.000ms
{"error":"MisdirectedRequest","message":"The request was directed at a server that is not able to produce a response."}

but in net/http

package main
import (
    "fmt"
    "net/http"
)
func main() {
    http.HandleFunc("/hello/gear", func (w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Welcome to my website!")
    })
   http.ListenAndServe(":3000", nil)
}

$curl curl http://localhost:3000/hello/gear/
404 not found

http2下会panic

现象:
panic: Header called after Handler finished
goroutine 214 [running]:
net/http.(*http2responseWriter).Header(0xc00025e0d8, 0x0)
/usr/local/go/src/net/http/h2_bundle.go:6310 +0x99
github.com/teambition/gear.(*Response).Header(0xc000262c00, 0xb62267)
/go/pkg/mod/github.com/teambition/[email protected]/response.go:85 +0x34
github.com/teambition/gear.(*Response).Get(0xc000262c00, 0xb62267, 0xc, 0x0, 0x0)
/go/pkg/mod/github.com/teambition/[email protected]/response.go:28 +0x2b
github.com/teambition/gear/logging.New.func2(0xc00024d890, 0xc0002f4630)
/go/pkg/mod/github.com/teambition/[email protected]/logging/logger.go:236 +0x690
github.com/teambition/gear/logging.(*Logger).Serve.func1()
/go/pkg/mod/github.com/teambition/[email protected]/logging/logger.go:533 +0x178
github.com/teambition/gear.runHooks(0xc00025e0e0, 0x1, 0x1)
/go/pkg/mod/github.com/teambition/[email protected]/response.go:186 +0x39
created by github.com/teambition/gear.(*App).ServeHTTP.func1
/go/pkg/mod/github.com/teambition/[email protected]/app.go:439 +0x179

原因:
https://github.com/teambition/gear/blob/v1.15.0/logging/logger.go#L236 会从Res中读取Header值:

ctx.Res.Get(gear.HeaderXRequestID);

而Res是nil:
https://github.com/golang/net/blob/ed066c81e75eba56dd9bd2139ade88125b855585/http2/server.go#L2525

Http2在处理完请求后在 handlerDone() 中会把Res置为nil:
https://github.com/golang/net/blob/ed066c81e75eba56dd9bd2139ade88125b855585/http2/server.go#L2629

日志输出是在 OnEnd 中调用res,(OnEnd挂在end hook上,被新的goroutine执行),所以panic了。
https://github.com/teambition/gear/blob/v1.15.0/logging/logger.go#L526

multi router example not work

func main() {
	// Create app
	app := gear.New()

	// Create views router
	viewRouter := gear.NewRouter()
	viewRouter.Get("/", func(ctx *gear.Context) error {
		return nil
	})
	// add more ...

	apiRouter := gear.NewRouter(gear.RouterOptions{
		Root:                  "/api",
		IgnoreCase:            true,
		FixedPathRedirect:     true,
		TrailingSlashRedirect: true,
	})
	// support one more middleware
	apiRouter.Get("/user/:id", func(ctx *gear.Context) error {
		return nil
	})
	// add more ..

	app.UseHandler(apiRouter) // Must add apiRouter first.
	app.UseHandler(viewRouter)
	// Start app at 3000
	app.Listen(":3000")
}

The viewRouter works, but apiRouter NOT.

支持该框架

找一个go web框架来学习,发现gear源码写的很有条理,很规范,支持支持

logging panic: Header called after Handler finished

运行场景:

app := gear.New()
app.UseHandler(logging.Default())

崩溃分析:

Response.WriteHeader()时,异步执行end hook,并结束请求:

// execute "end hooks" with LIFO order after Response.WriteHeader.
// they run in a goroutine, in order to not block current process.
if len(r.endHooks) > 0 {
	go runHooks(r.endHooks)
}

而logging 在运行时需打印Header相关信息,故有几率出现Header called after Handler finished

func (l *Logger) Serve(ctx *gear.Context) error {
	log := l.FromCtx(ctx)
	// Add a "end hook" to flush logs
	ctx.OnEnd(func() {
		// Ignore empty log
		if len(log) == 0 {
			return
		}
		log["Status"] = ctx.Res.Status()
		log["Type"] = ctx.Res.Type()
		log["Length"] = ctx.Res.Get(gear.HeaderContentLength)
		l.consume(log, ctx)
	})
	return nil
}

undefined: http.ErrAbortHandler

ritsus-iMac:fingerprint zhaoyili$ go get github.com/teambition/gear
# github.com/teambition/gear src/github.com/teambition/gear/app.go:343: undefined: http.ErrAbortHandler src/github.com/teambition/gear/app.go:386: app.Server.Shutdown undefined (type *http.Server has no field or method Shutdown) src/github.com/teambition/gear/app.go:388: app.Server.Close undefined (type *http.Server has no field or method Close) src/github.com/teambition/gear/response.go:169: undefined: http.PushOptions src/github.com/teambition/gear/response.go:170: undefined: http.Pusher src/github.com/teambition/gear/util.go:354: undefined: url.PathEscape

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.