From fd37f48211ff9a3db5446f94d538a05015e3ed56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jun 2026 21:49:59 +0000 Subject: [PATCH 1/6] Bump morgan from 1.10.1 to 1.11.0 in the production-dependencies group Bumps the production-dependencies group with 1 update: [morgan](https://github.com/expressjs/morgan). Updates `morgan` from 1.10.1 to 1.11.0 - [Release notes](https://github.com/expressjs/morgan/releases) - [Changelog](https://github.com/expressjs/morgan/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/morgan/compare/1.10.1...1.11.0) --- updated-dependencies: - dependency-name: morgan dependency-version: 1.11.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: production-dependencies ... Signed-off-by: dependabot[bot] --- package-lock.json | 24 ++++++++---------------- package.json | 2 +- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9774eab..2018e62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "express": "^5.2.1", "express-prom-bundle": "^8.0.0", "jsonwebtoken": "^9.0.0", - "morgan": "^1.10.1" + "morgan": "^1.11.0" }, "engines": { "node": ">=16.0.0" @@ -859,31 +859,23 @@ } }, "node_modules/morgan": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", - "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.11.0.tgz", + "integrity": "sha512-zSkVu3t18r39pw4ixfBKvfZi3y2UOqr7d4WYwcj3m8nXpEQK4rPO6GLzs/CExoRgmX3y9EjmmcXqv6jq0SK46g==", "license": "MIT", "dependencies": { "basic-auth": "~2.0.1", "debug": "2.6.9", "depd": "~2.0.0", - "on-finished": "~2.3.0", + "on-finished": "~2.4.1", "on-headers": "~1.1.0" }, "engines": { "node": ">= 0.8.0" - } - }, - "node_modules/morgan/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" }, - "engines": { - "node": ">= 0.8" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ms": { diff --git a/package.json b/package.json index 927f2ff..2fb0627 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "express": "^5.2.1", "express-prom-bundle": "^8.0.0", "jsonwebtoken": "^9.0.0", - "morgan": "^1.10.1" + "morgan": "^1.11.0" }, "overrides": { "jws": "^3.2.3" From e0e50ec631b0cf26d5fbe6cbf6e5dd43a6fc59fe Mon Sep 17 00:00:00 2001 From: Jack Myers Date: Sun, 14 Jun 2026 16:53:30 +0800 Subject: [PATCH 2/6] feat: add an ENV var to configure trusting additional proxy IPs/subnets --- README.md | 8 ++++++++ index.js | 11 +++++++++-- tests.sh | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfcbbd5..a62686a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This image is executed as non root by default and is fully compliant with Kubern - [Basic Usage](#basic-usage) - [Choose your ports](#choose-your-ports) - [Use your own certificates](#use-your-own-certificates) +- [Trust additional proxy IPs](#trust-additional-proxy-ips) - [Decode JWT header](#decode-jwt-header) - [Disable ExpressJS log lines](#disable-expressjs-log-lines) - [Do not log specific path](#do-not-log-specific-path) @@ -96,6 +97,13 @@ You can use volume mounting to substitute the certificate and private key with y You can use the environment variables `HTTPS_CERT_FILE` and `HTTPS_KEY_FILE` to define the location of existing certificate and private key inside container. +## Trust additional proxy IPs + +By default, Express is configured to trust forwarded proxy headers from loopback, link-local, and private IP ranges. To also trust additional proxy IPs or subnets, set `ADDITIONAL_TRUSTED_PROXIES` to a single value or a comma-separated list. + + docker run -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,203.0.113.10" -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 + + ## Decode JWT header If you specify the header that contains the JWT, the echo output will contain the decoded JWT. Use the `JWT_HEADER` environment variable for this. diff --git a/index.js b/index.js index a7b92c6..006d49e 100644 --- a/index.js +++ b/index.js @@ -17,11 +17,18 @@ const { PROMETHEUS_WITH_METHOD = 'true', PROMETHEUS_WITH_STATUS = 'true', PROMETHEUS_METRIC_TYPE = 'summary', - MAX_HEADER_SIZE = 1048576 + MAX_HEADER_SIZE = 1048576, + ADDITIONAL_TRUSTED_PROXIES } = process.env const maxHeaderSize = parseInt(MAX_HEADER_SIZE, 10) || 1048576; +const trustProxy = [ + 'loopback', + 'linklocal', + 'uniquelocal', + ...(ADDITIONAL_TRUSTED_PROXIES || '').split(',').map(proxy => proxy.trim()).filter(Boolean) +]; const sleep = promisify(setTimeout); const metricsMiddleware = promBundle({ @@ -34,7 +41,7 @@ const metricsMiddleware = promBundle({ const app = express() app.set('json spaces', 2); -app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); +app.set('trust proxy', trustProxy); if(PROMETHEUS_ENABLED === 'true') { app.use(metricsMiddleware); diff --git a/tests.sh b/tests.sh index c6fa41d..0bee232 100755 --- a/tests.sh +++ b/tests.sh @@ -237,6 +237,22 @@ fi message " Stop containers " stop_and_remove +message " Start container with additional trusted proxies " +docker run -d --rm -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,198.51.100.0/24" --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:testing +wait_for_ready + +REQUEST=$(curl -s -H "X-Forwarded-For: 203.0.113.10, 198.51.100.1, 2001:db8::1" http://localhost:8080/) +if [[ "$(echo "$REQUEST" | jq -r '.ip')" == '203.0.113.10' ]]; then + passed "Additional trusted proxies passed." +else + failed "Additional trusted proxies failed." + echo "$REQUEST" | jq + exit 1 +fi + +message " Stop containers " +stop_and_remove + message " Start container with different internal ports " docker run -d --rm -e HTTP_PORT=8888 -e HTTPS_PORT=9999 --name http-echo-tests -p 8080:8888 -p 8443:9999 -t mendhak/http-https-echo:testing wait_for_ready From 48e1cdb26aa46a5a93a403e0982c65fb42e523d7 Mon Sep 17 00:00:00 2001 From: Jack Myers Date: Sun, 14 Jun 2026 16:58:23 +0800 Subject: [PATCH 3/6] fix(test): ignore `curl` exit code when sending a large header --- tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.sh b/tests.sh index c6fa41d..e34b2ba 100755 --- a/tests.sh +++ b/tests.sh @@ -225,7 +225,7 @@ fi message " Make request with a header exceeding limit." LARGE_HEADER_VALUE=$(head -c 5000 &1) +REQUEST=$(curl -v -k -H "Large-Header: $LARGE_HEADER_VALUE" https://localhost:8443/ 2>&1 || true) if echo "$REQUEST" | grep -q "HTTP/1.1 431 Request Header Fields Too Large"; then passed "Large header test resulted in HTTP 431." else From 8528b224797df6763dc11e6559a2750d311ad700 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 14 Jun 2026 09:44:29 +0000 Subject: [PATCH 4/6] Bump qs from 6.15.0 to 6.15.2 Bumps [qs](https://github.com/ljharb/qs) from 6.15.0 to 6.15.2. - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](https://github.com/ljharb/qs/compare/v6.15.0...v6.15.2) --- updated-dependencies: - dependency-name: qs dependency-version: 6.15.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2018e62..d6b2533 100644 --- a/package-lock.json +++ b/package-lock.json @@ -982,9 +982,9 @@ } }, "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" From eeebe097f035c0ee8b2bd82f3d9a6c047b0fa04d Mon Sep 17 00:00:00 2001 From: mendhak Date: Sun, 14 Jun 2026 10:55:53 +0100 Subject: [PATCH 5/6] Version 41 --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d86685f..0411a19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## Version `41` - 2026-06-14 +* Added support for additional trusted proxies via `ADDITIONAL_TRUSTED_PROXIES` by [JackMyers001](https://github.com/mendhak/docker-http-https-echo/pull/101) +* Express update includes the new way of catching all paths + ## Version `40` - 2026-03-20 * Echo back cookies and signed cookies From 2c642afdfe74bec4d7d1ea2284bf2e8b262e5872 Mon Sep 17 00:00:00 2001 From: mendhak Date: Sun, 14 Jun 2026 11:00:10 +0100 Subject: [PATCH 6/6] References updated to v 41 --- README.md | 42 +++++++++++++++++++++--------------------- docker-compose.yml | 2 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index a62686a..92c59a7 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ It comes with various options that can manipulate the response output, see the t ![browser](./screenshots/screenshot.png) -The image is available on [Docker Hub](https://hub.docker.com/r/mendhak/http-https-echo): `mendhak/http-https-echo:40` -The image is available on [Github Container Registry](https://github.com/mendhak/docker-http-https-echo/pkgs/container/http-https-echo): `ghcr.io/mendhak/http-https-echo:40` +The image is available on [Docker Hub](https://hub.docker.com/r/mendhak/http-https-echo): `mendhak/http-https-echo:41` +The image is available on [Github Container Registry](https://github.com/mendhak/docker-http-https-echo/pkgs/container/http-https-echo): `ghcr.io/mendhak/http-https-echo:41` Please do not use the `:latest` tag as it will break without warning, use a specific version instead. @@ -47,7 +47,7 @@ This image is executed as non root by default and is fully compliant with Kubern Run with Docker - docker run -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 + docker run -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 Or run with Docker Compose @@ -64,13 +64,13 @@ You can choose a different internal port instead of 8080 and 8443 with the `HTTP In this example I'm setting http to listen on 8888, and https to listen on 9999. - docker run -e HTTP_PORT=8888 -e HTTPS_PORT=9999 -p 8080:8888 -p 8443:9999 --rm -t mendhak/http-https-echo:40 + docker run -e HTTP_PORT=8888 -e HTTPS_PORT=9999 -p 8080:8888 -p 8443:9999 --rm -t mendhak/http-https-echo:41 With docker compose, this would be: my-http-listener: - image: mendhak/http-https-echo:40 + image: mendhak/http-https-echo:41 environment: - HTTP_PORT=8888 - HTTPS_PORT=9999 @@ -86,7 +86,7 @@ The certificates are at `/app/fullchain.pem` and `/app/testpk.pem`. You can use volume mounting to substitute the certificate and private key with your own. my-http-listener: - image: mendhak/http-https-echo:40 + image: mendhak/http-https-echo:41 ports: - "8080:8080" - "8443:8443" @@ -101,14 +101,14 @@ You can use the environment variables `HTTPS_CERT_FILE` and `HTTPS_KEY_FILE` to By default, Express is configured to trust forwarded proxy headers from loopback, link-local, and private IP ranges. To also trust additional proxy IPs or subnets, set `ADDITIONAL_TRUSTED_PROXIES` to a single value or a comma-separated list. - docker run -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,203.0.113.10" -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 + docker run -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,203.0.113.10" -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 ## Decode JWT header If you specify the header that contains the JWT, the echo output will contain the decoded JWT. Use the `JWT_HEADER` environment variable for this. - docker run -e JWT_HEADER=Authentication -p 8080:8080 -p 8443:8443 --rm -it mendhak/http-https-echo:40 + docker run -e JWT_HEADER=Authentication -p 8080:8080 -p 8443:8443 --rm -it mendhak/http-https-echo:41 Now make your request with `Authentication: eyJ...` header (it should also work with the `Authentication: Bearer eyJ...` schema too): @@ -121,7 +121,7 @@ And in the output you should see a `jwt` section. In the log output set the environment variable `DISABLE_REQUEST_LOGS` to true, to disable the specific ExpressJS request log lines. The ones like `::ffff:172.17.0.1 - - [03/Jan/2022:21:31:51 +0000] "GET /xyz HTTP/1.1" 200 423 "-" "curl/7.68.0"`. The JSON output will still appear. - docker run --rm -e DISABLE_REQUEST_LOGS=true --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 + docker run --rm -e DISABLE_REQUEST_LOGS=true --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 ## Do not log specific path @@ -130,12 +130,12 @@ Set the environment variable `LOG_IGNORE_PATH` to a path or a regex you would li This can help reduce noise from healthchecks in orchestration/infrastructure like Swarm, Kubernetes, ALBs, etc. # Ignore a single path - docker run -e LOG_IGNORE_PATH=/ping -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 + docker run -e LOG_IGNORE_PATH=/ping -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 # Ignore multiple paths - docker run -e LOG_IGNORE_PATH="^\/ping|^\/health|^\/metrics" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 + docker run -e LOG_IGNORE_PATH="^\/ping|^\/health|^\/metrics" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 # Ignore all paths - docker run -e LOG_IGNORE_PATH=".*" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 - docker run -e LOG_IGNORE_PATH="^" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 + docker run -e LOG_IGNORE_PATH=".*" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 + docker run -e LOG_IGNORE_PATH="^" -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 @@ -162,7 +162,7 @@ Will contain a `json` property in the response/output. You can disable new lines in the log output by setting the environment variable `LOG_WITHOUT_NEWLINE`. For example, ```bash -docker run -e LOG_WITHOUT_NEWLINE=true -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 +docker run -e LOG_WITHOUT_NEWLINE=true -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 ``` ## Send an empty response @@ -170,7 +170,7 @@ docker run -e LOG_WITHOUT_NEWLINE=true -p 8080:8080 -p 8443:8443 --rm -t mendhak You can disable the JSON output in the response by setting the environment variable `ECHO_BACK_TO_CLIENT`. For example, ```bash -docker run -e ECHO_BACK_TO_CLIENT=false -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 +docker run -e ECHO_BACK_TO_CLIENT=false -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 ``` ## Custom status code @@ -251,7 +251,7 @@ You can have environment variables (that are visible to the echo server's proces Pass the `ECHO_INCLUDE_ENV_VARS=1` environment variable in. ```bash -docker run -d --rm -e ECHO_INCLUDE_ENV_VARS=1 --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 +docker run -d --rm -e ECHO_INCLUDE_ENV_VARS=1 --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 ``` Then do a normal request via curl or browser, and you will see the `env` property in the response body. @@ -291,7 +291,7 @@ openssl pkcs12 -export -in cert.pem -inkey testpk.pem -out certpkcs12.pfx By default, the headers in the response body are lowercased. To attempt to preserve the case of headers in the response body, set the environment variable `PRESERVE_HEADER_CASE` to true. ```bash -docker run -e PRESERVE_HEADER_CASE=true -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 +docker run -e PRESERVE_HEADER_CASE=true -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:41 ``` ## Override the response body with a file @@ -300,7 +300,7 @@ To override the response body with a file, set the environment variable `OVERRID The file path needs to be in the `/app` directory. ```bash -docker run -d --rm -v ${PWD}/test.html:/app/test.html -p 8080:8080 -e OVERRIDE_RESPONSE_BODY_FILE_PATH=/test.html -t mendhak/http-https-echo:40 +docker run -d --rm -v ${PWD}/test.html:/app/test.html -p 8080:8080 -e OVERRIDE_RESPONSE_BODY_FILE_PATH=/test.html -t mendhak/http-https-echo:41 ``` ## Set a maximum header size @@ -308,7 +308,7 @@ docker run -d --rm -v ${PWD}/test.html:/app/test.html -p 8080:8080 -e OVERRIDE_R You can use the `MAX_HEADER_SIZE` environment variable to set a maximum header size in bytes. The default is 1MB. ```bash -docker run -d --rm -e MAX_HEADER_SIZE=1000 -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 +docker run -d --rm -e MAX_HEADER_SIZE=1000 -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 ``` ## Cookies and Signed Cookies @@ -316,7 +316,7 @@ docker run -d --rm -e MAX_HEADER_SIZE=1000 -p 8080:8080 -p 8443:8443 -t mendhak Make a request with a `Cookie` header and the response will include the cookies: ```bash -docker run -d --rm --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 +docker run -d --rm --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 ``` Then make a request with a cookie header: @@ -328,7 +328,7 @@ curl -s http://localhost:8080/ -H "Cookie: foo=bar; baz=qux" To enable signed cookie support, set the `COOKIE_SECRET` environment variable. Signed cookies appear in the `signedCookies` section of the response: ```bash -docker run -d --rm -e COOKIE_SECRET=mysecretkey123 --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:40 +docker run -d --rm -e COOKIE_SECRET=mysecretkey123 --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:41 ``` Now you need to generate a signed cookie, and send it in the header. Here's a convenience node snippet: diff --git a/docker-compose.yml b/docker-compose.yml index 2e4fb1d..3250591 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: my-http-listener: - image: mendhak/http-https-echo:40 + image: mendhak/http-https-echo:41 environment: - HTTP_PORT=8888 - HTTPS_PORT=9999