Loading config/proxyplus.yaml +4 −0 Changes for config/proxyplus.yaml: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -87,6 +87,10 @@ proxyplus: # long-lived streaming responses (a live camera feed, a large file transfer) or a genuinely # stuck backend call tying up every worker at once; a healthy pool never gets close to this. h2_dispatch_queue_max: 256 # Largest request body (upload, git push, ...) accepted per request, in MiB. The body is # buffered in memory before being forwarded upstream, so this is also the per-upload # memory cost. 0 = libhttppp's compiled-in default (~4 MB). max_request_body_mb: 512 pid_file: "/run/proxyplus.pid" recovery_mode: false Loading src/config/BootstrapConfig.cpp +4 −0 Changes for src/config/BootstrapConfig.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -240,6 +240,10 @@ void BootstrapConfig::loadAndValidate() { readInt(conf, "/proxyplus/process/h2_dispatch_queue_max", 256); cfg.h1DispatchQueueMax = readInt(conf, "/proxyplus/process/h1_dispatch_queue_max", 256); cfg.maxRequestBodyMb = readInt(conf, "/proxyplus/process/max_request_body_mb", 512); if (cfg.maxRequestBodyMb < 0) throw ConfigValidationError("process.max_request_body_mb must be >= 0"); cfg.pidFile = readValue(conf, "/proxyplus/pid_file", ""); cfg.recoveryMode = readBool(conf, "/proxyplus/recovery_mode", false) ? RecoveryMode::Recover Loading src/config/BootstrapConfig.h +9 −0 Changes for src/config/BootstrapConfig.h: 9 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -143,6 +143,15 @@ struct AppConfig { // default for the same reason h2DispatchQueueMax is: degrade to a fast 503 out of the box. int h1DispatchQueueMax = 256; // Per-connection request-body ceiling, applied to every accepted HTTP connection via // libhttppp::HttpRequest::setMaxUploadSize() (see HttpProxyController::CreateConnection). // libhttppp's own compiled-in default (DEFAULT_UPLOADSIZE, ~4 MB) is far too small for a // reverse proxy: an H2 request body over it gets RST_STREAM ENHANCE_YOUR_CALM, which broke // a 5 MiB `git push` to git.tuxist.de. The body is still fully buffered in memory before // being forwarded upstream, so this is also the per-upload memory cost. In MiB; // 0 = keep libhttppp's compiled-in default. int maxRequestBodyMb = 512; RecoveryMode recoveryMode = RecoveryMode::Normal; MaintenanceMode maintenanceMode = MaintenanceMode::Off; }; Loading src/http/HttpProxyServer.h +14 −3 Changes for src/http/HttpProxyServer.h: 14 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); void RequestEvent(libhttppp::HttpRequest &curreq, const int tid, ULONG_PTR args) override; Loading Loading @@ -84,6 +85,12 @@ public: // that fix, a backend exception left the stream queued forever with no response ever sent. bool shouldOffloadH2Dispatch(libhttppp::HttpRequest &, uint32_t) const override; protected: // Applies maxRequestBodyMb (see BootstrapConfig.h) to each newly accepted connection -- // libhttppp enforces HttpRequest::getMaxUploadSize() on the connection-level request, // so this is the one place every H1/H2 connection passes through before its first body. void CreateConnection(std::shared_ptr<netplus::con> &res) override; private: struct AuthOutcome { bool authenticated = false; Loading Loading @@ -153,6 +160,7 @@ private: int _upstreamTimeoutSeconds; int _h2DispatchQueueMax; int _h1DispatchQueueMax; int _maxRequestBodyMb; }; // Binds the listener socket(s) *at construction time* (see main.cpp / spec "Privilege Loading @@ -177,7 +185,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); // SNI virtual hosting variant: certsByHostname carries one CertificateBundle per domain // sharing this listener (see ListenerConfig::tlsProfiles) instead of the single cert/key Loading @@ -193,7 +202,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); void run(); Loading Loading @@ -225,6 +235,7 @@ private: int _upstreamTimeoutSeconds; int _h2DispatchQueueMax; int _h1DispatchQueueMax; int _maxRequestBodyMb; }; } // namespace proxyplus::httpproxy src/main.cpp +2 −2 Changes for src/main.cpp: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -357,7 +357,7 @@ int main(int argc, char **argv) { listener, sniCerts, configStore, authService, pluginManager, loadBalancer, connectionPool, &acmeChallenges, cfg.idleConnectionTimeoutSeconds, cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax)); cfg.h1DispatchQueueMax, cfg.maxRequestBodyMb)); auto *server = httpServers.back().get(); auto allProfiles = configStore.listTlsProfiles(); for (const auto &profileName : tlsProfiles) { Loading @@ -379,7 +379,7 @@ int main(int argc, char **argv) { listener, certPathFor(cfg, profile), keyPathFor(cfg, profile), configStore, authService, pluginManager, loadBalancer, connectionPool, &acmeChallenges, cfg.idleConnectionTimeoutSeconds, cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax)); cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax, cfg.maxRequestBodyMb)); if (!profile.empty()) { auto *server = httpServers.back().get(); certManager.registerReloadCallback(profile, [server, &cfg, profile] { Loading Loading
config/proxyplus.yaml +4 −0 Changes for config/proxyplus.yaml: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -87,6 +87,10 @@ proxyplus: # long-lived streaming responses (a live camera feed, a large file transfer) or a genuinely # stuck backend call tying up every worker at once; a healthy pool never gets close to this. h2_dispatch_queue_max: 256 # Largest request body (upload, git push, ...) accepted per request, in MiB. The body is # buffered in memory before being forwarded upstream, so this is also the per-upload # memory cost. 0 = libhttppp's compiled-in default (~4 MB). max_request_body_mb: 512 pid_file: "/run/proxyplus.pid" recovery_mode: false Loading
src/config/BootstrapConfig.cpp +4 −0 Changes for src/config/BootstrapConfig.cpp: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -240,6 +240,10 @@ void BootstrapConfig::loadAndValidate() { readInt(conf, "/proxyplus/process/h2_dispatch_queue_max", 256); cfg.h1DispatchQueueMax = readInt(conf, "/proxyplus/process/h1_dispatch_queue_max", 256); cfg.maxRequestBodyMb = readInt(conf, "/proxyplus/process/max_request_body_mb", 512); if (cfg.maxRequestBodyMb < 0) throw ConfigValidationError("process.max_request_body_mb must be >= 0"); cfg.pidFile = readValue(conf, "/proxyplus/pid_file", ""); cfg.recoveryMode = readBool(conf, "/proxyplus/recovery_mode", false) ? RecoveryMode::Recover Loading
src/config/BootstrapConfig.h +9 −0 Changes for src/config/BootstrapConfig.h: 9 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -143,6 +143,15 @@ struct AppConfig { // default for the same reason h2DispatchQueueMax is: degrade to a fast 503 out of the box. int h1DispatchQueueMax = 256; // Per-connection request-body ceiling, applied to every accepted HTTP connection via // libhttppp::HttpRequest::setMaxUploadSize() (see HttpProxyController::CreateConnection). // libhttppp's own compiled-in default (DEFAULT_UPLOADSIZE, ~4 MB) is far too small for a // reverse proxy: an H2 request body over it gets RST_STREAM ENHANCE_YOUR_CALM, which broke // a 5 MiB `git push` to git.tuxist.de. The body is still fully buffered in memory before // being forwarded upstream, so this is also the per-upload memory cost. In MiB; // 0 = keep libhttppp's compiled-in default. int maxRequestBodyMb = 512; RecoveryMode recoveryMode = RecoveryMode::Normal; MaintenanceMode maintenanceMode = MaintenanceMode::Off; }; Loading
src/http/HttpProxyServer.h +14 −3 Changes for src/http/HttpProxyServer.h: 14 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -51,7 +51,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); void RequestEvent(libhttppp::HttpRequest &curreq, const int tid, ULONG_PTR args) override; Loading Loading @@ -84,6 +85,12 @@ public: // that fix, a backend exception left the stream queued forever with no response ever sent. bool shouldOffloadH2Dispatch(libhttppp::HttpRequest &, uint32_t) const override; protected: // Applies maxRequestBodyMb (see BootstrapConfig.h) to each newly accepted connection -- // libhttppp enforces HttpRequest::getMaxUploadSize() on the connection-level request, // so this is the one place every H1/H2 connection passes through before its first body. void CreateConnection(std::shared_ptr<netplus::con> &res) override; private: struct AuthOutcome { bool authenticated = false; Loading Loading @@ -153,6 +160,7 @@ private: int _upstreamTimeoutSeconds; int _h2DispatchQueueMax; int _h1DispatchQueueMax; int _maxRequestBodyMb; }; // Binds the listener socket(s) *at construction time* (see main.cpp / spec "Privilege Loading @@ -177,7 +185,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); // SNI virtual hosting variant: certsByHostname carries one CertificateBundle per domain // sharing this listener (see ListenerConfig::tlsProfiles) instead of the single cert/key Loading @@ -193,7 +202,8 @@ public: int idleTimeoutSeconds = 0, int upstreamTimeoutSeconds = 60, int h2DispatchQueueMax = 256, int h1DispatchQueueMax = 256); int h1DispatchQueueMax = 256, int maxRequestBodyMb = 0); void run(); Loading Loading @@ -225,6 +235,7 @@ private: int _upstreamTimeoutSeconds; int _h2DispatchQueueMax; int _h1DispatchQueueMax; int _maxRequestBodyMb; }; } // namespace proxyplus::httpproxy
src/main.cpp +2 −2 Changes for src/main.cpp: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -357,7 +357,7 @@ int main(int argc, char **argv) { listener, sniCerts, configStore, authService, pluginManager, loadBalancer, connectionPool, &acmeChallenges, cfg.idleConnectionTimeoutSeconds, cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax)); cfg.h1DispatchQueueMax, cfg.maxRequestBodyMb)); auto *server = httpServers.back().get(); auto allProfiles = configStore.listTlsProfiles(); for (const auto &profileName : tlsProfiles) { Loading @@ -379,7 +379,7 @@ int main(int argc, char **argv) { listener, certPathFor(cfg, profile), keyPathFor(cfg, profile), configStore, authService, pluginManager, loadBalancer, connectionPool, &acmeChallenges, cfg.idleConnectionTimeoutSeconds, cfg.upstreamRequestTimeoutSeconds, cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax)); cfg.h2DispatchQueueMax, cfg.h1DispatchQueueMax, cfg.maxRequestBodyMb)); if (!profile.empty()) { auto *server = httpServers.back().get(); certManager.registerReloadCallback(profile, [server, &cfg, profile] { Loading