From 997ef104fbee36c5630a3aedf12f6a6a3912d310 Mon Sep 17 00:00:00 2001 From: Faizan Javed Date: Sun, 9 Aug 2026 21:27:51 +0000 Subject: [PATCH 1/4] Fixed CORS issues and update performance count fetching logic Signed-off-by: Faizan Javed --- gatsby-config.js | 35 +++ src/sections/Counters/index.js | 14 +- src/sections/Meshery/Features-Col/index.js | 46 +++- .../How-meshery-works/specs/data-card.js | 74 +++--- src/sections/Projects/Nighthawk/index.js | 241 ++++++++++++++---- 5 files changed, 312 insertions(+), 98 deletions(-) diff --git a/gatsby-config.js b/gatsby-config.js index 19c2baad345d46..f2ebae1332df7b 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -42,6 +42,41 @@ collectionIgnoreGlobs.length > 0 : console.info("Build Scope includes all collections"); module.exports = { ...(pathPrefix != null ? { pathPrefix } : {}), + // cloud.layer5.io's CORS allowlist only permits https://layer5.io/https://www.layer5.io, + // so browser fetches from any local `gatsby develop` session are blocked cross-origin. + // This dev-only proxy (no effect on `gatsby build`) routes those requests through the + // same origin as the dev server so they succeed locally too. + // + // Gatsby's built-in `proxy` config uses `got`, whose `req.pipe(got.stream(...))` wiring + // has a bug that breaks TLS certificate verification for bodiless GET requests in this + // Gatsby/Node version combination (reproduced in isolation, confirmed deterministic). + // `developMiddleware` with Node's built-in `https` module sidesteps it entirely. + ...(isDevelopment + ? { + developMiddleware: (app) => { + app.use("/api/*", (req, res) => { + const https = require("https"); + const proxyReq = https.request( + `https://cloud.layer5.io${req.originalUrl}`, + { + method: req.method, + headers: { accept: req.headers.accept || "*/*" }, + }, + (proxyRes) => { + res.writeHead(proxyRes.statusCode, proxyRes.headers); + proxyRes.pipe(res); + }, + ); + proxyReq.on("error", (err) => { + res + .status(502) + .json({ error: "Proxy request failed", message: err.message }); + }); + proxyReq.end(); + }); + }, + } + : {}), siteMetadata: { title: "Layer5 - Expect more from your infrastructure", description: diff --git a/src/sections/Counters/index.js b/src/sections/Counters/index.js index 7f90f142f3e0d8..5ef8669febfe66 100644 --- a/src/sections/Counters/index.js +++ b/src/sections/Counters/index.js @@ -5,15 +5,23 @@ import Counter from "../../reusecore/Counter"; import CounterSectionWrapper from "./counterSection.style"; -export const URL = "https://cloud.layer5.io/api/performance/results/total"; +// cloud.layer5.io's CORS allowlist only permits https://layer5.io/https://www.layer5.io, +// so local `gatsby develop` sessions use the dev-only proxy from gatsby-config.js instead. +export const URL = + process.env.NODE_ENV === "development" + ? "/api/performance/results/total" + : "https://cloud.layer5.io/api/performance/results/total"; const Counters = () => { const [performanceCount, setPerformanceCount] = useState(0); useEffect(() => { fetch(URL) - .then(response => response.json()) - .then(result => setPerformanceCount(result.total_runs)); + .then((response) => response.json()) + .then((result) => setPerformanceCount(result.totalRuns)) + .catch((error) => { + console.log("Failed to fetch performance count:", error.message); + }); }, []); return ( diff --git a/src/sections/Meshery/Features-Col/index.js b/src/sections/Meshery/Features-Col/index.js index 9b33e6683ad9b9..aa6aaf9bb19df6 100644 --- a/src/sections/Meshery/Features-Col/index.js +++ b/src/sections/Meshery/Features-Col/index.js @@ -18,7 +18,22 @@ function getServiceFeature(service, index) { - + + + + {service.content} @@ -38,7 +53,7 @@ function getFeatureBlock(feature, index, performanceCount) { {feature.services.map((service, index) => - getServiceFeature(service, index) + getServiceFeature(service, index), )} @@ -47,9 +62,16 @@ function getFeatureBlock(feature, index, performanceCount) { duration={5} separator="," end={ - feature.count.value !== 0 ? feature.count.value : performanceCount + feature.count.description === "performance tests run" + ? performanceCount + : feature.count.value + } + suffix={ + feature.count.description == "components" || + feature.count.description == "cloud native integrations" + ? "+" + : " " } - suffix= {(feature.count.description == "components" || feature.count.description == "cloud native integrations") ? "+" : " "} />

{feature.count.description}

@@ -60,7 +82,12 @@ function getFeatureBlock(feature, index, performanceCount) { const Features = () => { const [performanceCount, setPerformanceCount] = useState(0); - const performanceCountEndpoint = "https://cloud.layer5.io/api/performance/results/total"; + // cloud.layer5.io's CORS allowlist only permits https://layer5.io/https://www.layer5.io, + // so local `gatsby develop` sessions use the dev-only proxy from gatsby-config.js instead. + const performanceCountEndpoint = + process.env.NODE_ENV === "development" + ? "/api/performance/results/total" + : "https://cloud.layer5.io/api/performance/results/total"; useEffect(() => { fetch(performanceCountEndpoint) @@ -72,13 +99,13 @@ const Features = () => { return response.json(); }) .then((resultcount) => { - if (resultcount && typeof resultcount.total_runs === "number") { - setPerformanceCount(resultcount.total_runs); + if (resultcount && typeof resultcount.totalRuns === "number") { + setPerformanceCount(resultcount.totalRuns); } }) .catch((error) => { console.log("Failed to fetch performance count:", error.message); - // Keep default value of 0 if fetch fails + // Keep default value of 0 if fetch fails }); }, []); @@ -94,12 +121,11 @@ const Features = () => { {data.map((feature, index) => - getFeatureBlock(feature, index, performanceCount) + getFeatureBlock(feature, index, performanceCount), )} ); }; - export default Features; diff --git a/src/sections/Meshery/How-meshery-works/specs/data-card.js b/src/sections/Meshery/How-meshery-works/specs/data-card.js index 1925ab2a72e0ce..5ee178c92c11b7 100644 --- a/src/sections/Meshery/How-meshery-works/specs/data-card.js +++ b/src/sections/Meshery/How-meshery-works/specs/data-card.js @@ -8,41 +8,39 @@ import Counter from "../../../../reusecore/Counter"; import { URL } from "../../../Counters/index"; const DataCardWrapper = styled.div` - background: ${props => props.theme.grey222222ToWhite}; + background: ${(props) => props.theme.grey222222ToWhite}; border-radius: 10px; - color: ${props => props.theme.text}; + color: ${(props) => props.theme.text}; padding: 2rem; transition: 0.8s cubic-bezier(0.2, 0.8, 0.2, 1); - - ul{ + + ul { list-style: none; padding: 0; } - .col-1 li{ - display: flex; - align-items: center; - vertical-align: center; - margin-bottom: 1.5rem; - img{ - margin-right: 1rem; - } - h5{ - font-weight: 600; - transition: 0.8s cubic-bezier(0.2, 0.8, 0.2, 1); - } - } - - .col-2 li { - h3{ - color: ${props => props.theme.secondaryColor}; - font-weight: 700; - } - p { - font-size: 16px; - } - } - - + .col-1 li { + display: flex; + align-items: center; + vertical-align: center; + margin-bottom: 1.5rem; + img { + margin-right: 1rem; + } + h5 { + font-weight: 600; + transition: 0.8s cubic-bezier(0.2, 0.8, 0.2, 1); + } + } + + .col-2 li { + h3 { + color: ${(props) => props.theme.secondaryColor}; + font-weight: 700; + } + p { + font-size: 16px; + } + } `; const DataCard = () => { @@ -51,7 +49,10 @@ const DataCard = () => { useEffect(() => { fetch(URL) .then((response) => response.json()) - .then((result) => setPerformanceCount(result.total_runs)); + .then((result) => setPerformanceCount(result.totalRuns)) + .catch((error) => { + console.log("Failed to fetch performance count:", error.message); + }); }, []); return ( @@ -77,22 +78,13 @@ const DataCard = () => {
  • - +

    Users

  • - +

    Performance tests run

  • diff --git a/src/sections/Projects/Nighthawk/index.js b/src/sections/Projects/Nighthawk/index.js index 89e71edf13df14..ae6f74a769dbf9 100644 --- a/src/sections/Projects/Nighthawk/index.js +++ b/src/sections/Projects/Nighthawk/index.js @@ -12,7 +12,8 @@ import cncf from "./images/cncf-white.svg"; const explain1 = "./images/Rectangle 479.webp"; const explain2 = "./images/optimizing-your-average-response-time.webp"; -const explain3 = "./images/Comparison-of-different-modes-of-delivery-of-service-mesh-network-functions.webp"; +const explain3 = + "./images/Comparison-of-different-modes-of-delivery-of-service-mesh-network-functions.webp"; import { Gnhwrapper, CardsContainer } from "./gnh.style"; @@ -25,7 +26,10 @@ const Projects = () => { useEffect(() => { fetch(URL) .then((response) => response.json()) - .then((result) => setPerformanceCount(result.total_runs)); + .then((result) => setPerformanceCount(result.totalRuns)) + .catch((error) => { + console.log("Failed to fetch performance count:", error.message); + }); }, []); return ( @@ -34,13 +38,18 @@ const Projects = () => {
    - +
    {/* */} -

    Unlock distributed systems behavioral performance analysis

    -

    Meshery is the easiest way to get started with Nighthawk on any cloud or platform.

    +

    + Unlock distributed systems behavioral performance analysis +

    +

    + Meshery is the easiest way to get started with Nighthawk on + any cloud or platform. +

    @@ -49,19 +58,27 @@ const Projects = () => {
    -

    +

    + +

    Histogram Statistics

    -

    +

    + +

    Meshery Tests

    -

    +

    + +

    Closed and Open-loop

    -

    +

    + +

    Percentiles calculated

    @@ -69,10 +86,17 @@ const Projects = () => {

    What is Nighthawk?

    -

    Nighthawk is a versatile HTTP load testing tool built out of a need to drill HTTP services with a constant request rate or with an adaptive request rate. Layer5 offers a custom distribution of Nighthawk with intelligent adaptive load controllers to automatically identify optimal configurations for your service mesh deployment. - As a Layer 7 performance characterization tool supporting HTTP/HTTPS/HTTP2, Nighthawk is Meshery's (and Envoy's) load generator and is written in C++. +

    + Nighthawk is a versatile HTTP load testing tool built out of a need + to drill HTTP services with a constant request rate or with an + adaptive request rate. Layer5 offers a custom distribution of + Nighthawk with intelligent adaptive load controllers to + automatically identify optimal configurations for your service mesh + deployment. As a Layer 7 performance characterization tool + supporting HTTP/HTTPS/HTTP2, Nighthawk is Meshery's (and Envoy's) + load generator and is written in C++.

    - +
    @@ -80,7 +104,11 @@ const Projects = () => {

    Nighthawk and Meshery

    -

    Meshery integrates Nighthawk as one of (currently) three choices of load generator for characterizing and managing the performance of service meshes and their workloads.

    +

    + Meshery integrates Nighthawk as one of (currently) three + choices of load generator for characterizing and managing the + performance of service meshes and their workloads.{" "} +

    @@ -97,8 +125,22 @@ const Projects = () => {

    Easing Management of the Nighthawk Lifecycle

    -

    As with a lot of open source projects, there is a lack of consistent tooling. This makes it difficult to have easily repeatable tests in that the building, deploying, and maintaining of Nighthawk instances (potentially a fleet of Nighthawk instances) is a burden without additional tooling.

    -
    @@ -106,8 +148,19 @@ const Projects = () => {

    Distributed Performance Management

    -

    Distributed load testing offers insight into system behaviors that arguably more accurately represent real world behaviors of services under load as that load comes from any number of sources.

    -

    Engineers need multi-variate load generation and analysis techniques offered through distributed performance analysis. Nighthawk is being improved so that it can be horizontally scalable - such that multiple instances will be cognizant of one another and able to coordinate amongst each other. Nighthawk is growing in popularity with Layer5, Google, Red Hat, and AWS investing into it.

    +

    + Distributed load testing offers insight into system behaviors that + arguably more accurately represent real world behaviors of services + under load as that load comes from any number of sources. +

    +

    + Engineers need multi-variate load generation and analysis techniques + offered through distributed performance analysis. Nighthawk is being + improved so that it can be horizontally scalable - such that + multiple instances will be cognizant of one another and able to + coordinate amongst each other. Nighthawk is growing in popularity + with Layer5, Google, Red Hat, and AWS investing into it. +

    @@ -116,7 +169,15 @@ const Projects = () => {

    SERVICE MESH PERFORMANCE COMPATIBILITY

    -

    Enabling Standards-based, Distributed Performance Management - Nighthawk integrates Meshery and Nighthawk. Through this integration Meshery facilitates Service Mesh Performance (SMP) compatibility for Nighthawk.

    +

    + Enabling Standards-based, Distributed Performance Management + - Nighthawk integrates Meshery and Nighthawk. Through this + integration Meshery facilitates{" "} + + Service Mesh Performance (SMP) + {" "} + compatibility for Nighthawk. +

    @@ -142,8 +203,16 @@ const Projects = () => { cpu image

    SCHEDULING AND ANALYSIS

    -

    Nighthawk integrates with Meshery and provides you with the ability to schedule performance tests or insert them into your CI pipeline.

    -

    Adaptive analysis in which you may run multi-stage performance tests and persist their results in a historical archive is also enabled through integration with Meshery.

    +

    + Nighthawk integrates with Meshery{" "} + and provides you with the ability to schedule performance + tests or insert them into your CI pipeline. +

    +

    + Adaptive analysis in which you may run multi-stage + performance tests and persist their results in a historical + archive is also enabled through integration with Meshery. +

    @@ -154,53 +223,134 @@ const Projects = () => {
    - Cloud Native Distributed Performance Management + Cloud Native Distributed Performance Management

    Standards-based, distributed performance management

    -

    Nighthawk will provide generally-available distributions of Nighthawk under different architectures and platforms and easy-to-use tooling for installation and operation. This will include creating distributions of Nighthawk as well as augmenting existing tooling, Meshery, to retrieve these arch-specific packages and update their deployments.

    +

    + Nighthawk will provide generally-available distributions of + Nighthawk under different architectures and platforms and + easy-to-use tooling for installation and operation. This will + include creating distributions of Nighthawk as well as + augmenting existing tooling, Meshery, to retrieve these + arch-specific packages and update their deployments. +

    -
    - + - + - + - + @@ -212,8 +362,11 @@ const Projects = () => {
    cncf logo -

    Participate in the state of the art.
    - Join us in the Cloud Native Computing Foundation's Service Mesh Working Group. +

    + {" "} + Participate in the state of the art.
    + Join us in the Cloud Native Computing Foundation's Service Mesh + Working Group.

    From ff5e129ef703d9bda549da6d7f029ae148c8a541 Mon Sep 17 00:00:00 2001 From: Faizan Javed Date: Mon, 10 Aug 2026 13:14:53 +0000 Subject: [PATCH 2/4] fix: restrict dev proxy middleware to GET requests on /api/* The proxy only forwards method and accept header, not body/Content-Type/ auth/cookies, so non-GET requests were silently broken. All current frontend usage of the relative /api/* path is GET-only, so scope the route accordingly instead of building out unused forwarding. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Faizan Javed --- gatsby-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gatsby-config.js b/gatsby-config.js index f2ebae1332df7b..85ef45c4332345 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -54,7 +54,7 @@ module.exports = { ...(isDevelopment ? { developMiddleware: (app) => { - app.use("/api/*", (req, res) => { + app.get("/api/*", (req, res) => { const https = require("https"); const proxyReq = https.request( `https://cloud.layer5.io${req.originalUrl}`, From 59173dbc1bb9c7e378085a29cf8587dabf9d6af1 Mon Sep 17 00:00:00 2001 From: Faizan Javed Date: Mon, 10 Aug 2026 14:32:27 +0000 Subject: [PATCH 3/4] fix: address CodeRabbit review findings on performance-counter proxy Add timeout + destroy on the dev proxy request and guard the error handler with res.headersSent so a mid-stream failure doesn't attempt a second response. Validate the performance API response (status and a finite totalRuns) before updating state in Counters, DataCard, and Nighthawk. Remove the hardcoded 250000 fallback in Features-Col so the default count of 0 is preserved on fetch failure. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Faizan Javed --- gatsby-config.js | 14 +++++++++++--- src/sections/Counters/index.js | 14 ++++++++++++-- src/sections/Meshery/Features-Col/index.js | 1 - .../Meshery/How-meshery-works/specs/data-card.js | 14 ++++++++++++-- src/sections/Projects/Nighthawk/index.js | 14 ++++++++++++-- 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/gatsby-config.js b/gatsby-config.js index 85ef45c4332345..9345aedbef1675 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -67,10 +67,18 @@ module.exports = { proxyRes.pipe(res); }, ); + proxyReq.setTimeout(10000, () => { + proxyReq.destroy(new Error("Proxy request timed out")); + }); proxyReq.on("error", (err) => { - res - .status(502) - .json({ error: "Proxy request failed", message: err.message }); + if (!res.headersSent) { + res + .status(502) + .json({ + error: "Proxy request failed", + message: err.message, + }); + } }); proxyReq.end(); }); diff --git a/src/sections/Counters/index.js b/src/sections/Counters/index.js index 5ef8669febfe66..6fe78fd8d0d358 100644 --- a/src/sections/Counters/index.js +++ b/src/sections/Counters/index.js @@ -17,8 +17,18 @@ const Counters = () => { useEffect(() => { fetch(URL) - .then((response) => response.json()) - .then((result) => setPerformanceCount(result.totalRuns)) + .then((response) => { + if (!response.ok) { + throw new Error(`Request failed with status ${response.status}`); + } + return response.json(); + }) + .then((result) => { + if (!Number.isFinite(result.totalRuns)) { + throw new Error("Invalid performance count received"); + } + setPerformanceCount(result.totalRuns); + }) .catch((error) => { console.log("Failed to fetch performance count:", error.message); }); diff --git a/src/sections/Meshery/Features-Col/index.js b/src/sections/Meshery/Features-Col/index.js index aa6aaf9bb19df6..789444bed386ed 100644 --- a/src/sections/Meshery/Features-Col/index.js +++ b/src/sections/Meshery/Features-Col/index.js @@ -93,7 +93,6 @@ const Features = () => { fetch(performanceCountEndpoint) .then((response) => { if (!response.ok) { - setPerformanceCount(250000); throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); diff --git a/src/sections/Meshery/How-meshery-works/specs/data-card.js b/src/sections/Meshery/How-meshery-works/specs/data-card.js index 5ee178c92c11b7..81fa311d466d79 100644 --- a/src/sections/Meshery/How-meshery-works/specs/data-card.js +++ b/src/sections/Meshery/How-meshery-works/specs/data-card.js @@ -48,8 +48,18 @@ const DataCard = () => { useEffect(() => { fetch(URL) - .then((response) => response.json()) - .then((result) => setPerformanceCount(result.totalRuns)) + .then((response) => { + if (!response.ok) { + throw new Error(`Request failed with status ${response.status}`); + } + return response.json(); + }) + .then((result) => { + if (!Number.isFinite(result.totalRuns)) { + throw new Error("Invalid performance count received"); + } + setPerformanceCount(result.totalRuns); + }) .catch((error) => { console.log("Failed to fetch performance count:", error.message); }); diff --git a/src/sections/Projects/Nighthawk/index.js b/src/sections/Projects/Nighthawk/index.js index ae6f74a769dbf9..5ee7a7c263cbad 100644 --- a/src/sections/Projects/Nighthawk/index.js +++ b/src/sections/Projects/Nighthawk/index.js @@ -25,8 +25,18 @@ const Projects = () => { useEffect(() => { fetch(URL) - .then((response) => response.json()) - .then((result) => setPerformanceCount(result.totalRuns)) + .then((response) => { + if (!response.ok) { + throw new Error(`Request failed with status ${response.status}`); + } + return response.json(); + }) + .then((result) => { + if (!Number.isFinite(result.totalRuns)) { + throw new Error("Invalid performance count received"); + } + setPerformanceCount(result.totalRuns); + }) .catch((error) => { console.log("Failed to fetch performance count:", error.message); }); From f3d96c05fd51c0c2f1becb624c7bcf9ddd1104e3 Mon Sep 17 00:00:00 2001 From: Faizan Javed Date: Mon, 10 Aug 2026 20:53:09 +0000 Subject: [PATCH 4/4] fix: reject negative and fractional totalRuns in performance count Number.isFinite allowed negative or non-integer values through to setPerformanceCount; require a finite, non-negative integer instead. Signed-off-by: Faizan Javed --- src/sections/Meshery/How-meshery-works/specs/data-card.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sections/Meshery/How-meshery-works/specs/data-card.js b/src/sections/Meshery/How-meshery-works/specs/data-card.js index 81fa311d466d79..a948b87d7f2aae 100644 --- a/src/sections/Meshery/How-meshery-works/specs/data-card.js +++ b/src/sections/Meshery/How-meshery-works/specs/data-card.js @@ -55,7 +55,7 @@ const DataCard = () => { return response.json(); }) .then((result) => { - if (!Number.isFinite(result.totalRuns)) { + if (!Number.isInteger(result.totalRuns) || result.totalRuns < 0) { throw new Error("Invalid performance count received"); } setPerformanceCount(result.totalRuns);
    + + + + +

    - Further the state of distributed
    - performance management. + Further the state of distributed
    + performance management.

    - Enable standards-based, distributed performance management through compatibility with the Service Mesh Performance (SMP) specification. + Enable standards-based, distributed performance + management through compatibility with the Service Mesh + Performance (SMP) specification.
    + + + + + -

    - Facilitate Nighthawk adoption. -

    - Deliver trusted, certified builds, distributed via the most popular package managers: apt, yum, Homebrew, and platforms: Docker and Meshery. - Bridge Nighthawk’s C++ with the lingua franca of Cloud Native: Golang. +

    Facilitate Nighthawk adoption.

    + Deliver trusted, certified builds, distributed via the + most popular package managers: apt, yum, Homebrew, and + platforms: Docker and Meshery. Bridge Nighthawk’s C++ + with the lingua franca of Cloud Native: Golang.
    + + + + +

    - Deliver easy-to-use, repeatable
    - tooling. + Deliver easy-to-use, repeatable
    + tooling.

    - To leverage Nighthawk as the performance characterization tool as used in the 30 patterns in the Service Mesh Patterns book. + To leverage Nighthawk as the performance + characterization tool as used in the 30 patterns in the + Service Mesh Patterns book.
    + + + + + -

    - Educate the ecosystem -

    - Educate the ecosystem through the CNCF Service Mesh Working Group. +

    Educate the ecosystem

    + Educate the ecosystem through the CNCF Service Mesh + Working Group.