简体   繁体   English

我如何 stream 与 grpc-web 并在同一端口上使用 REST API?

[英]How do I stream with grpc-web and use a REST API on the same port?

I have a server witten in Go that uses cmux to allow multiple protocols to run on the same port, but there's a limitation specified in the README saying that我在 Go 中有一个服务器,它使用cmux来允许多个协议在同一个端口上运行,但是 README 中指定了一个限制说

cmux matches the connection when it's accepted. cmux在连接被接受时匹配它。 For example, one connection can be either gRPC or REST, but not both.例如,一个连接可以是 gRPC 或 REST,但不能同时是两者。 That is, we assume that a client connection is either used for gRPC or REST.也就是说,我们假设客户端连接用于 gRPC 或 REST。

I need the browser to be able to both stream from grpc-web and call a REST API on the same port, but the browser reuses the same connection and causes the muxing to not work.我需要浏览器能够同时从 grpc-web 访问 stream 并调用 REST API 在同一个端口上,但浏览器重用相同的连接并导致复用不工作。

This is a pretty tricky problem to identify.这是一个非常棘手的问题。 Since browsers prefer to use an existing TCP connection for pipelining, the mux tends to send packets to the wrong protocol handler, for example it could send grpc-web packets to REST, and vice versa.由于浏览器更喜欢使用现有的 TCP 连接进行流水线操作,因此多路复用器倾向于将数据包发送到错误的协议处理程序,例如它可以将grpc-web数据包发送到 REST,反之亦然。 Luckily, there is a pretty simple solution for this:幸运的是,有一个非常简单的解决方案:

package main

listener := net.Listen("tcp", ":2289")
multiplexer := cmux.New(listener)
grpcListener := multiplexer.Match(cmux.HTTP2())
httpListener := multiplexer.Match(cmux.HTTP1Fast())
grpcServer := grpc.Server()
wrappedGrpc := grpcweb.WrapServer(grpcServer)
go func() {
  httpServer := echo.New()
  (&http.Server{
      Handler: http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
        if strings.Contains(req.Header.Get("Access-Control-Request-Headers"), "x-grpc-web") || req.Header.Get("x-grpc-web") == "1" || req.Header.Get("Sec-Websocket-Protocol") == "grpc-websockets" {
          inst.API.GrpcWebServer.ServeHTTP(resp, req)
        } else {
          httpServer.ServeHTTP(resp, req)
      }
    }),
  }).Serve(httpListener)
}()

go func() {
  grpcServer.Serve(grpcListener)
}()

go func() {
  multiplexer.Serve()
}()

How does this work?这是如何运作的?

Essentially, instead of using cmux 's default muxing (which only muxes per-connection) we registered a new mini http server handler on all HTTP requests coming in, which then lets us explicitly check headers and call handlers directly.本质上,我们没有使用cmux的默认多路复用(仅对每个连接进行多路复用),而是在所有传入的 HTTP 请求上注册了一个新的迷你 http 服务器处理程序,然后我们可以显式检查标头并直接调用处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以在前端 javascript 中使用纯 grpc(不是 grpc-web)吗 - Can I use pure grpc (not grpc-web) in frontend javascript 使用 gRPC-web 调用 google text to voice api - Use gRPC-web to call google text to speech api 如何在grpc-web中将枚举值转换为字符串 - How to turn enum values to strings in grpc-web 如何将python gRPC服务的尾随元数据发送到grpc-web客户端? - How to send trailing metadata from python gRPC service to grpc-web client? 找不到VueJS Grpc-Web模块 - VueJS Grpc-Web module not found 在没有 NodeJS 的情况下使用 GRPC-Web - Using GRPC-Web without NodeJS 如何仅在Web浏览器中安全地使用REST API? - How do I securely use a REST API solely from within a web browser? 如何将gRPC定义的API引入Web浏览器 - How to bring a gRPC defined API to the web browser 类型错误:无法使用 grpc-web 在 react js 应用程序中读取未定义的属性(读取“MethodInfo”) - TypeError: Cannot read properties of undefined (reading 'MethodInfo') in react js app using grpc-web 如何捕获在我的应用程序中播放的音频流,然后将其用作 Web Audio API 的有效输入以进行可视化? - How can I capture an audio stream playing in my application, and then it use it as a valid input for Web Audio API for visualization?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM