From 59aa6cdcacadfaf6a3a8b2b8fee057bc68e06a6f Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 11 Jun 2025 14:24:42 -0700 Subject: [PATCH] feat: Support health checks. Endpoints can configure a `health` path which will be used for health checks at server startup. The SDK will consider an endpoint healthy only after a valid http response for th healt path was returned. At startup the SDK will perform up to max 10 retries with exponential backoff delay. --- sdks/typescript/package-lock.json | 19 +- sdks/typescript/package.json | 5 +- sdks/typescript/sample/package-lock.json | 5 +- .../sample/src/specs/sample.spec.ts | 2 +- .../test-data/config/test-server-config.yml | 3 +- ...659f4a847abbce3501f7c930395e67e892293e.req | 14 + ...59f4a847abbce3501f7c930395e67e892293e.resp | 16 + ...6ddfd148c8217903b4b84b5b4fdef71e0a8b4.req} | 2 +- ...ddfd148c8217903b4b84b5b4fdef71e0a8b4.resp} | 359 +++++++++++------- sdks/typescript/src/index.ts | 54 ++- 10 files changed, 332 insertions(+), 147 deletions(-) create mode 100644 sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.req create mode 100644 sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.resp rename sdks/typescript/sample/test-data/recordings/{ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.req => e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.req} (87%) rename sdks/typescript/sample/test-data/recordings/{ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.resp => e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.resp} (72%) diff --git a/sdks/typescript/package-lock.json b/sdks/typescript/package-lock.json index ba8ddc3..8a3ed69 100644 --- a/sdks/typescript/package-lock.json +++ b/sdks/typescript/package-lock.json @@ -1,18 +1,19 @@ { "name": "test-server-sdk", - "version": "0.1.0", + "version": "0.2.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "test-server-sdk", - "version": "0.1.0", + "version": "0.2.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "axios": "^1.6.0", "extract-zip": "^2.0.1", - "tar": "^6.2.0" + "tar": "^6.2.0", + "yaml": "^2.8.0" }, "devDependencies": { "@types/node": "^20.11.0", @@ -578,6 +579,18 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", diff --git a/sdks/typescript/package.json b/sdks/typescript/package.json index c953e83..3f7ef39 100644 --- a/sdks/typescript/package.json +++ b/sdks/typescript/package.json @@ -1,6 +1,6 @@ { "name": "test-server-sdk", - "version": "0.2.1", + "version": "0.2.2", "description": "TypeScript SDK for test-server", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,7 +27,8 @@ "dependencies": { "axios": "^1.6.0", "extract-zip": "^2.0.1", - "tar": "^6.2.0" + "tar": "^6.2.0", + "yaml": "^2.8.0" }, "devDependencies": { "@types/node": "^20.11.0", diff --git a/sdks/typescript/sample/package-lock.json b/sdks/typescript/sample/package-lock.json index 56d0ded..fba71ee 100644 --- a/sdks/typescript/sample/package-lock.json +++ b/sdks/typescript/sample/package-lock.json @@ -20,13 +20,14 @@ }, "..": { "name": "test-server-sdk", - "version": "0.1.0", + "version": "0.2.1", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "axios": "^1.6.0", "extract-zip": "^2.0.1", - "tar": "^6.2.0" + "tar": "^6.2.0", + "yaml": "^2.8.0" }, "devDependencies": { "@types/node": "^20.11.0", diff --git a/sdks/typescript/sample/src/specs/sample.spec.ts b/sdks/typescript/sample/src/specs/sample.spec.ts index 971223c..b80c33b 100644 --- a/sdks/typescript/sample/src/specs/sample.spec.ts +++ b/sdks/typescript/sample/src/specs/sample.spec.ts @@ -26,7 +26,7 @@ describe('Sample Test Suite (with test-server)', () => { beforeAll(async () => { try { - serverProcess = startTestServer(sampleTestServerOptions); + serverProcess = await startTestServer(sampleTestServerOptions); console.log(`[SampleSpec] test-server started with PID: ${serverProcess.pid}. Waiting for it to be ready...`); // TODO(amirh): Replace this with some sort of a readiness check. await new Promise(resolve => setTimeout(resolve, 500)); diff --git a/sdks/typescript/sample/test-data/config/test-server-config.yml b/sdks/typescript/sample/test-data/config/test-server-config.yml index 2d1c9b3..ba65a56 100644 --- a/sdks/typescript/sample/test-data/config/test-server-config.yml +++ b/sdks/typescript/sample/test-data/config/test-server-config.yml @@ -1,6 +1,7 @@ endpoints: - - target_host: www.github.com + - target_host: github.com target_type: https target_port: 443 source_type: http source_port: 18080 + health: healthz diff --git a/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.req b/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.req new file mode 100644 index 0000000..de1b7fc --- /dev/null +++ b/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.req @@ -0,0 +1,14 @@ +b4d6e60a9b97e7b98c63df9308728c5c88c0b40c398046772c63447b94608b4d +Server Address: github.com +Port: 443 +Protocol: https +******************************************************************************** +GET /healthz HTTP/1.1 +Accept: */* +Accept-Encoding: gzip, deflate +Accept-Language: * +Connection: keep-alive +Sec-Fetch-Mode: cors +User-Agent: node + + diff --git a/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.resp b/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.resp new file mode 100644 index 0000000..857e051 --- /dev/null +++ b/sdks/typescript/sample/test-data/recordings/62fe0f67bb2dc1d57b9629e608659f4a847abbce3501f7c930395e67e892293e.resp @@ -0,0 +1,16 @@ +Status code: 200 +Date: Wed, 11 Jun 2025 21:20:28 GMT +Accept-Ranges: bytes +Set-Cookie: _gh_sess=RUXx6I8rXzwAWTFBzCcNLMpA%2BIfAw19leo8%2F6hxTBGEr2XfLP%2BZPLguz%2BpQPQZL%2FWUfw2tJpqLFdQ0ihM1LGU9TJZ2Eel46thCU8OnCKlZMJ2RGVKcQr%2FBQuwO32xXFMbywgBNRfsyNpat0U%2FEQqQRx2Gx9kwLxwliM6o%2BWPU3XHZvnfJRSMjbkdLIT2UDrTPOg9yYE3xUEd9M3q%2BbG5vPsTWY5IJleB%2Brfx9DhiYzrjlDWEjc%2FVuTpn6bWHmELj119LAt3P83gw%2Fc1pT9NNhw%3D%3D--WP%2FOWsLLuU0K7OWX--s%2B8qDjT7cpMciWgIREzfYw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax +Set-Cookie: _octo=GH1.1.499478081.1749676828; Path=/; Domain=github.com; Expires=Thu, 11 Jun 2026 21:20:28 GMT; Secure; SameSite=Lax +Set-Cookie: logged_in=no; Path=/; Domain=github.com; Expires=Thu, 11 Jun 2026 21:20:28 GMT; HttpOnly; Secure; SameSite=Lax +Content-Length: 58 +Cache-Control: no-cache +X-Frame-Options: DENY +Strict-Transport-Security: max-age=31536000; includeSubDomains; preload +Content-Type: text/html +X-Github-Request-Id: 751F:290523:51C25B9:54C9428:6849F31C + +

200 OK

+Service ready. + diff --git a/sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.req b/sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.req similarity index 87% rename from sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.req rename to sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.req index 2f77fc2..aa70eab 100644 --- a/sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.req +++ b/sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.req @@ -1,5 +1,5 @@ b4d6e60a9b97e7b98c63df9308728c5c88c0b40c398046772c63447b94608b4d -Server Address: www.github.com +Server Address: github.com Port: 443 Protocol: https ******************************************************************************** diff --git a/sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.resp b/sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.resp similarity index 72% rename from sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.resp rename to sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.resp index ab52f8e..094ec65 100644 --- a/sdks/typescript/sample/test-data/recordings/ca9b35b322af83c3f595466821787602f129e60dcb452204602324f6d37e339f.resp +++ b/sdks/typescript/sample/test-data/recordings/e3e781293e37b42d98f86c15d676ddfd148c8217903b4b84b5b4fdef71e0a8b4.resp @@ -1,22 +1,22 @@ Status code: 200 -Etag: W/"49b00c2729aabe34772737b14b29783e" -Strict-Transport-Security: max-age=31536000; includeSubdomains; preload -Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin -Vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, Accept-Language,Accept-Encoding, Accept, X-Requested-With -Content-Language: en-US -X-Frame-Options: deny -Date: Tue, 06 May 2025 20:58:52 GMT Content-Type: text/html; charset=utf-8 +Etag: W/"5009389a23caa1c5a3257cd764ab3a25" +Server: github.com +Date: Wed, 11 Jun 2025 21:20:19 GMT +Vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With, Accept-Language,Accept-Encoding, Accept, X-Requested-With +X-Frame-Options: deny +X-Github-Request-Id: 751F:290523:51C2855:54C96E8:6849F31C +Content-Language: en-US +Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin Accept-Ranges: bytes -Set-Cookie: _gh_sess=VlggKSJl0Kea8g2gfq5W%2BR24wqT8%2FpOsFZJPFnTaB%2BGrDrRgTlyGWdggTEhrxL0QffbJ6Oarppb8kXyJgl6H%2BOdvSv2v8G%2F%2BOQH9xCHmfv%2BC3Xd2FVzvZhwS5mSUQ869oW5w9Prt7mnuQGfpGeNH2MzJw3S7UyEYrS9v1%2BhHyKu7KFLX2zTRjYu8Du6A9QZ6LPvSKjdhpUWTS0t9op3U8jfaC%2FscKYhh0QgxshNq3GB7r8n7URy5fL74WVoAy5pBuE%2FgxuzQoa3wqo721y8%2Bcg%3D%3D--ZQZOR3yWbsyLUeyO--56LWHxqOtN%2B5ao8OhDO1jw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax -Set-Cookie: _octo=GH1.1.1712589872.1746565137; Path=/; Domain=github.com; Expires=Wed, 06 May 2026 20:58:57 GMT; Secure; SameSite=Lax -Set-Cookie: logged_in=no; Path=/; Domain=github.com; Expires=Wed, 06 May 2026 20:58:57 GMT; HttpOnly; Secure; SameSite=Lax -X-Github-Request-Id: EE48:2F89ED:1B73E12:1C6FD32:681A7811 +Set-Cookie: _gh_sess=9AJjfcBcvvDhTMZn3VhEgHubK%2FWewlGrXt84TqdOEMz26hoRsNaORPdke%2FoFyrepO%2F87iJwfNOsNpjWKrj0HLXdbPf1EGrliSvPrtnk7wearXHlo3SiS0hqWKPHjZ6BWimxJ%2FS9Yy4jZFRLBIjelJXd8qNO6BKamScCM4sI3hj%2F5i6VRhi0QZkHLRTHmbqtCB2DliLQQmn752lxn%2BQA%2BAl6XbXM0yvwy09YaGstHIv2U8%2Bc2Xi0CLEatWI3ShKk3H9bmWCmq2M7TMNeoR%2BuYog%3D%3D--wN4D23YbzoiIqYbo--5tbMmX%2FzOHfPsExlVqR5mg%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax +Set-Cookie: _octo=GH1.1.1871580905.1749676829; Path=/; Domain=github.com; Expires=Thu, 11 Jun 2026 21:20:29 GMT; Secure; SameSite=Lax +Set-Cookie: logged_in=no; Path=/; Domain=github.com; Expires=Thu, 11 Jun 2026 21:20:29 GMT; HttpOnly; Secure; SameSite=Lax +Content-Security-Policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com github.githubassets.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com www.youtube-nocookie.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com images.ctfassets.net/8aevphvgewt8/; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com assets.ctfassets.net/8aevphvgewt8/ videos.ctfassets.net/8aevphvgewt8/; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/ Cache-Control: max-age=0, private, must-revalidate +Strict-Transport-Security: max-age=31536000; includeSubdomains; preload X-Content-Type-Options: nosniff X-Xss-Protection: 0 -Content-Security-Policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com github.githubassets.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com www.youtube-nocookie.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com github.githubassets.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/ -Server: github.com @@ -32,7 +32,7 @@ Server: github.com data-color-mode="dark" data-dark-theme="dark" data-color-mode="light" data-light-theme="light" data-dark-theme="dark" data-a11y-animated-images="system" data-a11y-link-underlines="true" - + data-css-features="prs_diff_containment" > @@ -47,80 +47,85 @@ Server: github.com - + - + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + GitHub · Build and ship software on a single, collaborative platform · GitHub @@ -130,13 +135,13 @@ Server: github.com - + - + @@ -189,10 +194,10 @@ Server: github.com - - - - + + + + @@ -202,6 +207,13 @@ Server: github.com + + + + + + + @@ -214,7 +226,7 @@ Server: github.com - + @@ -241,10 +253,10 @@ Server: github.com - - - - + + + + + @@ -271,8 +283,8 @@ Server: github.com - - + +