From e353aa67090a231c9dac2aa91bc6934c8911c646 Mon Sep 17 00:00:00 2001 From: vicanso Date: Sun, 10 Nov 2024 19:11:39 +0800 Subject: [PATCH] feat: server and location support grpc web module --- src/config/common.rs | 2 ++ src/proxy/location.rs | 2 ++ src/proxy/server.rs | 29 +++++++++++++++++++++++++++++ src/proxy/server_conf.rs | 2 ++ web/src/i18n/en.ts | 3 +++ web/src/i18n/zh.ts | 3 +++ web/src/pages/Locations.tsx | 17 +++++++++++++++-- web/src/pages/Servers.tsx | 11 ++++++++++- web/src/states/config.ts | 2 ++ 9 files changed, 68 insertions(+), 3 deletions(-) diff --git a/src/config/common.rs b/src/config/common.rs index c0a50f6..3183ea3 100644 --- a/src/config/common.rs +++ b/src/config/common.rs @@ -316,6 +316,7 @@ pub struct LocationConf { pub plugins: Option>, pub client_max_body_size: Option, pub includes: Option>, + pub grpc_web: Option, pub remark: Option, } @@ -427,6 +428,7 @@ pub struct ServerConf { pub prometheus_metrics: Option, pub otlp_exporter: Option, pub includes: Option>, + pub modules: Option>, pub remark: Option, } diff --git a/src/proxy/location.rs b/src/proxy/location.rs index 308ed07..c046637 100644 --- a/src/proxy/location.rs +++ b/src/proxy/location.rs @@ -142,6 +142,7 @@ pub struct Location { pub accepted: AtomicU64, pub processing: AtomicI32, pub upstream: String, + pub grpc_web: bool, client_max_body_size: usize, } @@ -212,6 +213,7 @@ impl Location { plugins: conf.plugins.clone(), accepted: AtomicU64::new(0), processing: AtomicI32::new(0), + grpc_web: conf.grpc_web.unwrap_or_default(), proxy_add_headers: format_headers(&conf.proxy_add_headers)?, proxy_set_headers: format_headers(&conf.proxy_set_headers)?, client_max_body_size: conf diff --git a/src/proxy/server.rs b/src/proxy/server.rs index d564c98..f3f2838 100644 --- a/src/proxy/server.rs +++ b/src/proxy/server.rs @@ -58,6 +58,8 @@ use pingora::cache::{ use pingora::http::{RequestHeader, ResponseHeader}; use pingora::listeners::TcpSocketOptions; use pingora::modules::http::compression::ResponseCompression; +use pingora::modules::http::grpc_web::{GrpcWeb, GrpcWebBridge}; +use pingora::modules::http::HttpModules; use pingora::protocols::http::error_resp; use pingora::protocols::Digest; use pingora::protocols::TimingDigest; @@ -154,6 +156,7 @@ pub struct Server { prometheus_metrics: String, #[cfg(feature = "full")] enabled_otel: bool, + modules: Option>, } pub struct ServerServices { @@ -219,6 +222,7 @@ impl Server { prometheus_metrics, #[cfg(feature = "full")] prometheus, + modules: conf.modules.clone(), }; Ok(s) } @@ -420,6 +424,16 @@ impl ProxyHttp for Server { fn new_ctx(&self) -> Self::CTX { State::new() } + fn init_downstream_modules(&self, modules: &mut HttpModules) { + let Some(value) = &self.modules else { + return; + }; + for item in value.iter() { + if item == "grpc-web" { + modules.add_module(Box::new(GrpcWeb)); + } + } + } async fn early_request_filter( &self, session: &mut Session, @@ -516,6 +530,21 @@ impl ProxyHttp for Server { } } if let Some(location) = &ctx.location { + if location.grpc_web { + // Initialize gRPC module for this request + let grpc = session + .downstream_modules_ctx + .get_mut::() + .ok_or_else(|| { + util::new_internal_error( + 500, + "grpc web bridge module should be added" + .to_string(), + ) + })?; + grpc.init(); + } + ctx.location_accepted = location.accepted.fetch_add(1, Ordering::Relaxed) + 1; ctx.location_processing = diff --git a/src/proxy/server_conf.rs b/src/proxy/server_conf.rs index 78d94c5..4a6e322 100644 --- a/src/proxy/server_conf.rs +++ b/src/proxy/server_conf.rs @@ -37,6 +37,7 @@ pub struct ServerConf { pub enabled_h2: bool, pub prometheus_metrics: Option, pub otlp_exporter: Option, + pub modules: Option>, } impl fmt::Display for ServerConf { @@ -107,6 +108,7 @@ impl From for Vec { tcp_fastopen: item.tcp_fastopen, prometheus_metrics: item.prometheus_metrics, otlp_exporter: item.otlp_exporter.clone(), + modules: item.modules.clone(), error_template, }); } diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts index 9440a6b..6f8e7ad 100644 --- a/web/src/i18n/en.ts +++ b/web/src/i18n/en.ts @@ -123,6 +123,8 @@ export default { accessLog: "Access Log Format", accessLogPlaceholder: "Input the format layout for access", enabledH2: "Enable Http2(h2c)", + modules: "Http Modules", + moduleslaceholder: "Select http modules for server", tlsCipherList: "Tls Cipher List", tlsCipherListPlaceholder: "Input the cipher list for protocols before tlsv1.3", @@ -170,6 +172,7 @@ export default { clientMaxBodySizePlaceholder: "Input the max body size(e.g. 1mb)", plugins: "Plugins", pluginsPlaceholder: "Select the plugins for location", + grpcWeb: "Grpc Web", remark: "Remark", }, upstream: { diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts index 8cf36e8..ae10130 100644 --- a/web/src/i18n/zh.ts +++ b/web/src/i18n/zh.ts @@ -120,6 +120,8 @@ export default { accessLog: "访问日志格式化", accessLogPlaceholder: "输入日志格式化模板", enabledH2: "启用http2(h2c)", + modules: "Http模块", + moduleslaceholder: "选择要使用的http模块", tlsCipherList: "tls密码套件列表", tlsCipherListPlaceholder: "输入tls密码套件列表,早于tls1.3版本认证使用", tlsCiphersuites: "tls密码套件列表", @@ -162,6 +164,7 @@ export default { clientMaxBodySizePlaceholder: "输入请求实体限制大小(如1mb)", plugins: "插件列表", pluginsPlaceholder: "选择location使用的相关插件", + grpcWeb: "Grpc Web", remark: "备注", }, upstream: { diff --git a/web/src/pages/Locations.tsx b/web/src/pages/Locations.tsx index 3b66f99..8e2a762 100644 --- a/web/src/pages/Locations.tsx +++ b/web/src/pages/Locations.tsx @@ -5,7 +5,11 @@ import React from "react"; import { ExForm, ExFormItem } from "@/components/ex-form"; import { pascal } from "radash"; import { z } from "zod"; -import { ExFormItemCategory, newStringOptions } from "@/constants"; +import { + ExFormItemCategory, + newBooleanOptions, + newStringOptions, +} from "@/constants"; import { formatLabel, newZodBytes, omitEmptyArray } from "@/helpers/util"; import { useSearchParams } from "react-router-dom"; import { useEffect } from "react"; @@ -132,10 +136,19 @@ export default function Locations() { label: i18n("includes"), placeholder: i18n("includesPlaceholder"), defaultValue: locationConfig.includes, - span: 6, + span: 3, category: ExFormItemCategory.MULTI_SELECT, options: newStringOptions(getIncludeOptions(), false), }, + { + name: "grpc_web", + label: locationI18n("grpcWeb"), + placeholder: "", + defaultValue: locationConfig.grpc_web, + span: 3, + category: ExFormItemCategory.RADIOS, + options: newBooleanOptions(), + }, { name: "weight", label: locationI18n("weight"), diff --git a/web/src/pages/Servers.tsx b/web/src/pages/Servers.tsx index fbac230..216d88c 100644 --- a/web/src/pages/Servers.tsx +++ b/web/src/pages/Servers.tsx @@ -124,12 +124,21 @@ export default function Servers() { category: ExFormItemCategory.RADIOS, options: newBooleanOptions(), }, + { + name: "modules", + label: serverI18n("modules"), + placeholder: serverI18n("moduleslaceholder"), + defaultValue: serverConfig.modules, + span: 3, + category: ExFormItemCategory.MULTI_SELECT, + options: newStringOptions(["grpc-web"], false), + }, { name: "includes", label: i18n("includes"), placeholder: i18n("includesPlaceholder"), defaultValue: serverConfig.includes, - span: 3, + span: 6, category: ExFormItemCategory.MULTI_SELECT, options: newStringOptions(getIncludeOptions(), false), }, diff --git a/web/src/states/config.ts b/web/src/states/config.ts index 6b7281a..7ecc0c8 100644 --- a/web/src/states/config.ts +++ b/web/src/states/config.ts @@ -38,6 +38,7 @@ export interface Location { client_max_body_size?: string; plugins?: string[]; includes?: string[]; + grpc_web?: boolean; remark?: string; } @@ -85,6 +86,7 @@ export interface Server { prometheus_metrics?: string; otlp_exporter?: string; includes?: string[]; + modules?: string[]; remark?: string; }