资讯动态

Apache APISIX grpc-web 插件:让浏览器 JavaScript 客户端直接调用 gRPC 服务

发布时间:2026/9/15 3:07:48 来源:尧图企业网站定制
Apache APISIX grpc-web 插件让浏览器 JavaScript 客户端直接调用 gRPC 服务【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix导读grpc-web是 Apache APISIX 中的一个代理型proxy插件它负责把来自 JavaScript 客户端的 gRPC Web搭建一套可复现的验证环境。插件简介与工作原理gRPC 原生基于 HTTP/2 与二进制 Protobuf 帧而浏览器环境无法直接发起或读取这类流量。gRPC Web 协议见 gRPC 官方 PROTOCOL-WEB.md正是为解决这一问题而生它定义了如何在 HTTP/1.1 之上承载 gRPC 调用。APISIX 的grpc-web插件在网关侧完成双向转换请求方向解析客户端以application/grpc-web系列 Content-Type 提交的请求将 URI 中的 proto 路径包名/服务名/方法名还原为 gRPC 路径把请求体解码并改写为application/grpc再按grpcscheme 转发给上游响应方向把上游 gRPC 服务返回的二进制帧及 trailergrpc-status、grpc-message重新编码为 gRPC Web 客户端可识别的格式并补全 CORS 相关响应头。从源码 apisix/plugins/grpc-web.lua 可以看出插件在access阶段完成请求转换在header_filter阶段注入 CORS 头在body_filter阶段改写响应体与 trailer三个阶段的职责划分非常清晰。插件版本为 0.1优先级为 505该值也登记在 conf/config.yaml.example 的插件列表中。Attributes 配置参数名称类型必填默认值描述cors_allow_headersstring否content-type,x-grpc-web,x-user-agent跨域请求时允许携带的请求头使用,分隔可以追加多个请求头。这是插件唯一的配置项。在源码 apisix/plugins/grpc-web.lua 中该字段的 schema 定义为字符串类型默认值常量DEFAULT_CORS_ALLOW_HEADERS与文档保持一致。它只影响OPTIONS预检响应中的Access-Control-Allow-Headers头示例见下文。启用插件在特定 Route 上启用grpc-web插件先获取管理接口的admin_keyadmin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)随后通过 Admin API 创建一条启用插件的路由curl http://127.0.0.1:9180/apisix/admin/routes/1 -H X-API-KEY: $admin_key -X PUT -d { uri:/grpc/web/*, plugins:{ grpc-web:{} }, upstream:{ scheme:grpc, type:roundrobin, nodes:{ 127.0.0.1:1980:1 } } }这里的要点plugins.grpc-web置为空对象即可使用全部默认配置如需自定义跨域请求头可写成grpc-web:{cors_allow_headers:grpc-accept-encoding}upstream.scheme必须为grpc指向后端 gRPC 服务的地址与端口测试用例 t/plugin/grpc-web.t 中的 TEST 1 使用同样的配置uri 为/grpc/web/*上游为127.0.0.1:50001TEST 15/16 则验证了自定义cors_allow_headers grpc-accept-encoding后预检响应头Access-Control-Allow-Headers变为该自定义值。必须使用前缀匹配路由重要使用grpc-web插件时路由必须采用前缀匹配模式如/*、/grpc/example/*。原因是gRPC Web 客户端会把 proto 中的包名、服务接口名、方法名等信息直接拼进 URI例如/path/a6.RouteService/Insert。如果使用绝对匹配如/grpc/web2/a6.RouteService/GetRoute插件将无法命中也就无法从 URI 中提取 proto 信息。这一约束在源码中有明确校验apisix/plugins/grpc-web.lua 在access阶段检查ctx.curr_req_matched[:ext]若不存在则直接返回 400并记录错误日志 routing configuration error, grpc-web plugin only supportsprefix matchingpattern routing。测试 t/plugin/grpc-web.t 的 TEST 7/8 正是构造了一条绝对匹配路由/grpc/web2/a6.RouteService/GetRoute来验证该报错行为。请求方法、Content-Type 与 CORS 支持gRPC Web 客户端就绪后即可从浏览器或 Node.js 向 APISIX 发起请求但需要注意以下协议约束支持的请求方法仅POST与OPTIONS后者用于浏览器 CORS 预检。源码 apisix/plugins/grpc-web.lua 中对OPTIONS直接返回 204对非POST方法记录错误并返回 400——测试 t/plugin/grpc-web.t 的 TEST 4OPTIONS → 204与 TEST 5GET → 400错误日志request method: \GET invalid分别覆盖了这两种分支支持的 Content-Typeapplication/grpc-web、application/grpc-web-text、application/grpc-webproto、application/grpc-web-textproto。这四种 MIME 在源码 apisix/plugins/grpc-web.lua 中被映射为两种编码方式不带-text的按binary处理请求体原样透传带-text的按base64处理请求体先 base64 解码再转发响应体再 base64 编码返回。测试 t/plugin/grpc-web.t 的 TEST 6 验证了传入application/json会被拒绝400错误日志request Content-Type: \application/json invalid。插件自动注入的 CORS 响应头无需额外启用cors插件grpc-web插件本身就会在响应中注入默认 CORS 头。从 apisix/plugins/grpc-web.lua 的header_filter阶段可以看到响应头值说明Access-Control-Allow-Origin*若上下文中没有cors_allow_origins即未叠加cors插件时设置Access-Control-Allow-MethodsPOST仅在OPTIONS预检响应中设置Access-Control-Allow-Headers配置项cors_allow_headers的值仅在OPTIONS预检响应中设置Access-Control-Expose-Headersgrpc-message,grpc-status让浏览器可以读取 gRPC trailer 中的状态信息Content-Type请求携带的原始 gRPC Web MIME保证响应 Content-Type 与客户端协议一致测试 t/plugin/grpc-web.t 的 TEST 14 断言了这些默认头TEST 10/11 则验证了当同时启用cors插件allow_origins http://test.com时Access-Control-Allow-Origin会保留为cors插件设置的值而不会被grpc-web覆盖且Access-Control-Expose-Headers始终存在。响应 trailer 的编码细节gRPC 调用的最终状态成功码0、错误码、错误消息由 gRPC 协议以 trailer 形式携带。浏览器读取不到原生 trailer因此grpc-web插件需要在body_filter阶段把 trailer 编码进响应体末尾。源码 apisix/plugins/grpc-web.lua 中完整实现了 gRPC Web 的 trailer 帧格式1 字节固定标志位0x804 字节大端序 trailer 长度n 字节 trailer 内容形如grpc-status:0\r\ngrpc-message:...\r\n。插件读取 NGINX 上游变量upstream_trailer_grpc_status与upstream_trailer_grpc_message该能力自 NGINX 1.13.10 起可用拼接成 trailer 帧后追加到响应体若请求采用base64编码则 trailer 帧也先做 base64 编码再追加。测试 t/plugin/grpc-web.t 的 TEST 12 用 curl 直接验证了响应体末尾存在grpc-status:0\r\ngrpc-message:的 trailer 内容。基于仓库测试框架的端到端验证仓库在 t/plugin/grpc-web 目录下提供了完整的 gRPC Web 联调环境可以直接复现上文所述全部行为a6/route.proto定义测试服务RouteService包含一元调用GetRoute(Query) returns (Route)与服务端流式调用GetRoutes(Query) returns (stream Route)a6/route_pb.js、a6/route_grpc_web_bin_pb.js、a6/route_grpc_web_text_pb.js由protoc与protoc-gen-grpc-web生成的二进制协议与文本协议客户端桩代码client.js基于grpc-web与xhr2的 Node.js 客户端node client.js BIN UNARY以二进制协议发起一元调用node client.js TEXT STREAM以文本协议发起服务端流式调用依赖见 package.jsongoogle-protobuf、grpc-web、xhr2server.go用 Go 标准grpc库实现的测试后端监听:50001内置hello/world两条路由数据支持一元与流式两种调用构建脚本见 setup.shnpm installgo build。测试脚本 t/plugin/grpc-web.t 将上述组件串联为 16 个用例从建路由、一元/流式代理TEST 2/3 的响应体同时包含数据帧与Status: { code: 0 ... }、OPTIONS 预检TEST 4、非法方法与非法 MIME 拒绝TEST 5/6、绝对匹配拒绝TEST 8、与cors插件叠加TEST 9-11到 trailer 校验TEST 12与默认/自定义 CORS 头校验TEST 14/16构成了插件行为最完整的可执行证据。删除插件如需移除grpc-web插件只需从 Route 配置中删除对应 JSON 配置。APISIX 会自动热加载无需重启即可生效curl http://127.0.0.1:9180/apisix/admin/routes/1 -H X-API-KEY: $admin_key -X PUT -d { uri:/grpc/web/*, plugins:{}, upstream:{ scheme:grpc, type:roundrobin, nodes:{ 127.0.0.1:1980:1 } } }删除后/grpc/web/*路径上的请求将不再经过 gRPC Web 协议转换而是按普通路由直接转发。小结grpc-web插件用极简的配置仅一个可选参数补全了浏览器到 gRPC 服务的最后一公里前缀匹配路由负责承载 proto 路径四种 Content-Type 覆盖二进制与文本两种 Web 协议变体内置 CORS 头满足浏览器跨域预检body_filter阶段的标准 trailer 帧编码则保证了 gRPC 状态能被 Web 客户端正确感知。结合 apisix/plugins/grpc-web.lua 的实现与 t/plugin/grpc-web.t 的 16 个测试用例开发者可以在自己的 APISIX 环境中快速复制这套验证流程把 gRPC 服务安全、规范地开放给前端应用。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价