Open tangx opened 2 years ago
it cause by operator deepcopy function: https://github.com/go-jarvis/rum-gonic/blob/0d721423e8f585e8a64a63f983d59f6ee79c7207/rum/group.go#L145
static fileserver use a different to create
func newStaticFile(method, path, filepath string) *StaticFile {
return &StaticFile{
method: method,
path: path,
filepath: filepath,
}
}
type StaticFile struct {
method string
path string
filepath string
}
actually, here is the key problem: https://github.com/go-jarvis/rum-gonic/blob/0d721423e8f585e8a64a63f983d59f6ee79c7207/rum/operator.go#L39
the below code create a new operator, with zero value
in all filed.
func (fact *OperatorFactory) NewOperator() Operator {
opc := reflect.New(fact.Type).Interface().(Operator)
return opc
}
when OperatorFactory create a new StaticFile
or StaticFS
operator , the filepath
in Staticfile
and fs
in StaticFS
are empty. so gin handler can not work.
type StaticFile struct {
method string
path string
filepath string
}
func (static *StaticFile) Path() string {
return static.path
}
func (static *StaticFile) Method() string {
return static.method
}
that's why fs.Open(file)
occur the panic.
runtime error: invalid memory address or nil pointer dereference
/usr/local/go/src/runtime/panic.go:221 (0x44a846)
panicmem: panic(memoryError)
/usr/local/go/src/runtime/signal_unix.go:735 (0x44a816)
sigpanic: panicmem()
/data/gopath/src/github.com/go-jarvis/rum-gonic/rum/fileserver.go:75 (0x89f919)
(*StaticFS).Output: f, err := static.fs.Open(file)
/data/gopath/src/github.com/go-jarvis/rum-gonic/rum/group.go:159 (0x8a08c1)
(*RouterGroup).handlerfunc.func1: ret, err := op.Output(c)
why can rum register handler successful
path
and method
value are both get from the origin operator
.the copy operator
function is called in handler generator r.handlerfunc(op)
. In this step, handler generator return a valid gin HandlerFunc
, but it may occur panic. for _, method := range httpx.UnmarshalMethods(mop.Method()) {
method = strings.TrimSpace(method)
// 有错就要报,免得找不到
// if len(method) == 0 {
// continue
// }
r.ginRG.Handle(method, path, r.handlerfunc(op))
}
https://github.com/go-jarvis/rum-gonic/commit/1be6d62ea66409a390d3887249628e3149394d4f
new interface OperatorDeepcopier
, call origin Deepcopy
method to create new operator
// DeepCopyOperator return a deepcopied operator
func DeepCopyOperator(op Operator) Operator {
if copier, ok := op.(OperatorDeepcopier); ok {
return copier.Deepcopy()
}
return NewOperatorFactory(op).New()
}
type OperatorDeepcopier interface {
Deepcopy() Operator
}
func (static *StaticFile) Deepcopy() Operator {
return &StaticFile{
method: static.method,
path: static.path,
filepath: static.filepath,
}
}