mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-04 21:32:15 +00:00
fix(login): http 2 memory leak's (#11830)
# Which Problems Are Solved All http 2 based connect-es clients caused memory leaks in our testing using the login v2 application as the host. # How the Problems Are Solved Switch to connect-rpc based http 1.1 transport for the login v2 # Additional Changes Improved the otel interceptor implementation and tests. # Additional Context - connect-rpc is only enabled for v2 API's so we have to make sure to not use any v1 apis in the login but this should be the case anyways. - Discussion #10562 --------- Co-authored-by: Max Peintner <[email protected]>
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
/**
|
||||
* Mock Zitadel Connect/gRPC server for testing trace propagation.
|
||||
* Mock Zitadel ConnectRPC server for testing trace propagation.
|
||||
* Captures incoming headers and writes them to a file for test assertions.
|
||||
*
|
||||
* Uses HTTP/2 with cleartext (h2c) to support gRPC protocol.
|
||||
*/
|
||||
const http2 = require("http2");
|
||||
const http = require("http");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
@@ -34,21 +31,18 @@ function safeJsonStringify(value) {
|
||||
// Store captured requests
|
||||
const capturedRequests = [];
|
||||
|
||||
// Handle HTTP/2 request
|
||||
function handleRequest(stream, headers, isHttp2 = true) {
|
||||
const method = isHttp2 ? headers[":method"] : headers.method;
|
||||
const url = isHttp2 ? headers[":path"] : headers.url;
|
||||
const server = http.createServer((req, res) => {
|
||||
const { method, url } = req;
|
||||
|
||||
// Capture trace headers
|
||||
const traceHeaders = {
|
||||
timestamp: new Date().toISOString(),
|
||||
method: method,
|
||||
url: url,
|
||||
traceparent: headers["traceparent"] || null,
|
||||
tracestate: headers["tracestate"] || null,
|
||||
baggage: headers["baggage"] || null,
|
||||
grpcAcceptEncoding: headers["grpc-accept-encoding"] || null,
|
||||
contentType: headers["content-type"] || null,
|
||||
method,
|
||||
url,
|
||||
traceparent: req.headers["traceparent"] || null,
|
||||
tracestate: req.headers["tracestate"] || null,
|
||||
baggage: req.headers["baggage"] || null,
|
||||
contentType: req.headers["content-type"] || null,
|
||||
};
|
||||
|
||||
capturedRequests.push(traceHeaders);
|
||||
@@ -60,24 +54,9 @@ function handleRequest(stream, headers, isHttp2 = true) {
|
||||
console.log(`[${traceHeaders.timestamp}] ${method} ${url}`);
|
||||
console.log(` traceparent: ${traceHeaders.traceparent || "(none)"}`);
|
||||
|
||||
// Helper to send response
|
||||
const sendResponse = (statusCode, contentType, body) => {
|
||||
if (isHttp2) {
|
||||
stream.respond({
|
||||
":status": statusCode,
|
||||
"content-type": contentType,
|
||||
"grpc-status": "0",
|
||||
"grpc-message": "OK",
|
||||
});
|
||||
stream.end(body);
|
||||
} else {
|
||||
stream.writeHead(statusCode, {
|
||||
"Content-Type": contentType,
|
||||
"grpc-status": "0",
|
||||
"grpc-message": "OK",
|
||||
});
|
||||
stream.end(body);
|
||||
}
|
||||
res.writeHead(statusCode, { "Content-Type": contentType });
|
||||
res.end(body);
|
||||
};
|
||||
|
||||
// Health check
|
||||
@@ -92,7 +71,7 @@ function handleRequest(stream, headers, isHttp2 = true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mock Connect/gRPC responses
|
||||
// Mock ConnectRPC responses
|
||||
// These are minimal responses to prevent the login app from crashing
|
||||
if (url.includes("GetLoginSettings") || url.includes("SettingsService")) {
|
||||
sendResponse(200, "application/json", safeJsonStringify({ settings: {} }));
|
||||
@@ -109,47 +88,20 @@ function handleRequest(stream, headers, isHttp2 = true) {
|
||||
} else {
|
||||
sendResponse(200, "application/json", safeJsonStringify({}));
|
||||
}
|
||||
}
|
||||
|
||||
// Create HTTP/2 server (cleartext for testing)
|
||||
const http2Server = http2.createServer();
|
||||
|
||||
http2Server.on("stream", (stream, headers) => {
|
||||
handleRequest(stream, headers, true);
|
||||
});
|
||||
|
||||
http2Server.on("error", (err) => console.error("HTTP/2 error:", err));
|
||||
server.on("error", (err) => console.error("Server error:", err));
|
||||
|
||||
// Also create HTTP/1.1 server for health checks from wget
|
||||
const httpServer = http.createServer((req, res) => {
|
||||
// Create a headers object compatible with handleRequest
|
||||
const headers = {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
...req.headers,
|
||||
};
|
||||
handleRequest(res, headers, false);
|
||||
});
|
||||
|
||||
// Start HTTP/2 server on main port
|
||||
http2Server.listen(PORT, "0.0.0.0", () => {
|
||||
console.log(`Mock Zitadel HTTP/2 server listening on port ${PORT}`);
|
||||
server.listen(PORT, "0.0.0.0", () => {
|
||||
console.log(`Mock Zitadel server listening on port ${PORT}`);
|
||||
console.log(`Captured headers will be written to: ${HEADERS_FILE}`);
|
||||
});
|
||||
|
||||
// Start HTTP/1.1 server on a different port for health checks
|
||||
const HEALTH_PORT = 7432;
|
||||
httpServer.listen(HEALTH_PORT, "0.0.0.0", () => {
|
||||
console.log(`Mock Zitadel HTTP/1.1 health server listening on port ${HEALTH_PORT}`);
|
||||
});
|
||||
|
||||
// Graceful shutdown
|
||||
process.on("SIGTERM", () => {
|
||||
console.log("Shutting down mock servers...");
|
||||
http2Server.close(() => {
|
||||
httpServer.close(() => {
|
||||
console.log("Mock servers stopped");
|
||||
process.exit(0);
|
||||
});
|
||||
console.log("Shutting down mock server...");
|
||||
server.close(() => {
|
||||
console.log("Mock server stopped");
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user