- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
tôi đang sử dụng Gin Gonic创建反向代理端点的框架,目标端点使用 grpc Gateway 提供服务使用下面给出的代码。这类似于为 Gin 建议的反向代理方法 đâyVà đây
ep1 := v1.Group("/ep1")
{
ep1.GET("/ep2", reverseProxy("http://localhost:50000"))
}
func reverseProxy(target string) gin.HandlerFunc {
url, err := url.Parse(target)
nếu err != nil {
log.Println("Reverse Proxy target url could not be parsed:", err)
trả về nil
}
proxy := httputil.NewSingleHostReverseProxy(url)
return func(c *gin.Context) {
proxy.ServeHTTP(c.Writer, c.Request)
}
}
但是,当实际向此 gin 端点 (/ep1/ep2) 发送请求时,会出现 go panic:
interface conversion: *http.timeoutWriter is not http.CloseNotifier: missing method CloseNotify
/usr/local/Cellar/go/1.8/libexec/src/runtime/panic.go:489 (0x10288df)
gopanic: reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
/usr/local/Cellar/go/1.8/libexec/src/runtime/iface.go:131 (0x100c3af)
additab: panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), iname})
/usr/local/Cellar/go/1.8/libexec/src/runtime/iface.go:79 (0x100bc34)
getitab: additab(m, true, canfail)
/usr/local/Cellar/go/1.8/libexec/src/runtime/iface.go:256 (0x100cbb8)
assertI2I: r.tab = getitab(inter, tab._type, false)
/path/to/vendor/github.com/gin-gonic/gin/response_writer.go:110 (0x14de6f3)
(*responseWriter).CloseNotify: return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
/usr/local/Cellar/go/1.8/libexec/src/net/http/httputil/reverseproxy.go:142 (0x14d4d12)
(*ReverseProxy).ServeHTTP: notifyChan := cn.CloseNotify()
/path/to/main.go:379 (0x16d2ead)
reverseProxy.func1: proxy.ServeHTTP(c.Writer, c.Request)
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/locale.go:12 (0x15737d9)
getLocaleMiddleware.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/session_cookie.go:27 (0x1574e7c)
getSessionCookieMiddleware.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/affiliate_api.go:27 (0x15729a1)
getAffiliateAPIMiddleware.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/metrics.go:17 (0x157465b)
getMetricsMiddleware.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/input_validations.go:75 (0x1572dcb)
getInputValidationMiddleware.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/logger.go:68 (0x1573aea)
LoggerWithWriter.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/middlewares/request_tracer.go:13 (0x1574d6c)
getTracerContext.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/vendor/github.com/gin-gonic/gin/recovery.go:45 (0x14e4b6a)
RecoveryWithWriter.func1: c.Next()
/path/to/vendor/github.com/gin-gonic/gin/context.go:97 (0x14d657a)
(*Context).Next: c.handlers[c.index](c)
/path/to/vendor/github.com/gin-gonic/gin/gin.go:284 (0x14dc710)
(*Engine).handleHTTPRequest: context.Next()
/path/to/vendor/github.com/gin-gonic/gin/gin.go:265 (0x14dc02b)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/Cellar/go/1.8/libexec/src/net/http/server.go:2967 (0x140fa53)
(*timeoutHandler).ServeHTTP.func1: h.handler.ServeHTTP(tw, r)
/usr/local/Cellar/go/1.8/libexec/src/runtime/asm_amd64.s:2197 (0x1054851)
关于为什么会发生这种情况或代码中有什么问题有什么想法吗?
câu trả lời hay nhất
我们发现这个问题是因为代码库没有直接使用 gin-gonic
của Run()
方法。相反,它在启动 http 服务器时使用超时,如下所示(在此处使用部分相关代码):
type H struct {
sync.Mutex
Engine *gin.Engine
listener net.Listener
running bool
}
.
.
.
var h H
s := &http.Server{
Addr: address,
Handler: http.TimeoutHandler(h.Engine, time.Duration(100000)*time.Millisecond, ""),
ReadTimeout: time.Duration(100000) * time.Millisecond,
WriteTimeout: time.Duration(100000) * time.Millisecond,
}
h.listener, err := net.Listen("tcp", s.Addr)
nếu err != nil {
return err
}
h.running = true
s.Serve(h.listener)
Nhưng,http.TimeoutHandler
并未实现 http://grokbase.com/t/gg/golang-dev/13796p5h1n/net-http-timeouthandler-vs-closenotify 中提到的 http.CloseNotifer
接口(interface)这导致了 panic
错误消息 interface conversion: *http.timeoutWriter is not http.CloseNotifier: missing method CloseNotify
因此,作为此问题的解决方法,将服务器处理程序修改为直接作为 gin 引擎,同时使用 http 的
。ReadTimeout
Và WriteTimeout
值。用于超时目的的服务器
修改后的代码不再 panic ,并导致成功的反向代理:
type H struct {
sync.Mutex
Engine *gin.Engine
listener net.Listener
running bool
}
.
.
.
var h H
s := &http.Server{
Addr: address,
Handler: h.Engine,
ReadTimeout: time.Duration(100000) * time.Millisecond,
WriteTimeout: time.Duration(100000) * time.Millisecond,
}
h.listener, err := net.Listen("tcp", s.Addr)
nếu err != nil {
return err
}
h.running = true
s.Serve(h.listener)
注意这里只有&http.Server
củaNgười xử lý
需要修改。此外,不需要修改问题中的原始反向代理代码。
关于Golang gin-gonic 反向代理导致 panic "interface conversion: *http.timeoutWriter is not http.CloseNotifier: missing method CloseNotify",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43670872/
我正在使用 Gin Gonic创建反向代理端点的框架,目标端点使用 grpc Gateway 提供服务使用下面给出的代码。这类似于为 Gin 建议的反向代理方法 here和 here ep1 := v
Tôi đang sử dụng go 1.4.2 và quá trình triển khai dường như không có CloseNotifier vì tôi muốn sử dụng nó trong một trình xử lý cuộc thăm dò dài, ví dụ: func Pollhandler(w http.ResponseWriter, r
我在我的应用程序中使用 CloseNotifier,代码如下所示 func Handler(res http.ResonseWriter, req *http.Request) { notif
Go 1.7 添加了 Context 到 http.Request。它会完全取代 http.CloseNotify 吗?我现在应该更喜欢它,而不用担心 CloseNotify 吗? 最佳答案 是的,但
Tôi là một lập trình viên xuất sắc, rất giỏi!