Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a798a22
Updating dev-build workflow to not rely on github secrets but instead…
DWBatmanPS Jun 20, 2025
83388bb
Pushing updated tags for images and updating release build workflow
DWBatmanPS Jun 20, 2025
53ac120
adding vailure verbosity to github actions
DWBatmanPS Jun 20, 2025
124952e
Fixing typo in release build workflow
DWBatmanPS Jun 20, 2025
743f392
correcting typo in release build workflow
DWBatmanPS Jun 20, 2025
1f3d25f
pushing typo correction
DWBatmanPS Jun 20, 2025
aecde2d
removing bad code block
DWBatmanPS Jun 20, 2025
2d062f7
updating container tags
DWBatmanPS Jun 20, 2025
fa465c3
updating tags to final syntax
DWBatmanPS Jun 20, 2025
1d4da48
updating release build workflow
DWBatmanPS Jun 20, 2025
e3a6522
correcting typos in release-build.yml
DWBatmanPS Jun 23, 2025
ea05291
adding missing character in docker tag
DWBatmanPS Jun 23, 2025
bf4e78a
Updating documentation and adding debug functionality to the applicat…
DWBatmanPS Jul 11, 2025
ada9dc5
Correcting readme docs.
DWBatmanPS Jul 11, 2025
9709a21
Comitting punctuation change
DWBatmanPS Jul 11, 2025
466dd6f
Merge pull request #2 from DWBatmanPS:docs-update
DWBatmanPS Jul 11, 2025
63c3040
correcting typo
DWBatmanPS Jul 11, 2025
6e81d94
Merge branch 'Adding-debug' of https://github.com/DWBatmanPS/headersa…
DWBatmanPS Jul 11, 2025
a032224
Merge pull request #3 from DWBatmanPS/Adding-debug
DWBatmanPS Jul 11, 2025
340232d
aligning main branch with upstream naming.
DWBatmanPS Jul 11, 2025
d76e40a
Set npm as the package ecosystem for Dependabot
DWBatmanPS Dec 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: "npm" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
16 changes: 12 additions & 4 deletions .github/workflows/dev-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
- name: Create SSL certificate and key
run: |
mkdir -p ./ssl/private
echo "${{ secrets.TEST_SSL_KEY }}" > ./ssl/private/secret.key
echo "${{ secrets.TEST_SSL_CERT }}" > ./ssl/private/cert.cer
openssl genrsa -out ./ssl/private/secret.key 2048
openssl req -new -x509 -key ./ssl/private/secret.key -out ./ssl/private/cert.cer -days 30 -subj "/CN=contoso.com"

- name: Create .env file
run: |
Expand Down Expand Up @@ -51,6 +51,8 @@ jobs:
EXPECTED_RESPONSE='{"method":"POST","url":"/","clientIP":"::1","headers":{"host":"localhost:8443","user-agent":"curl/8.5.0","accept":"*/*","content-type":"application/json","content-length":"27"}}'
if [ "$RESPONSE" != "$EXPECTED_RESPONSE" ]; then
echo "Test failed: Response does not match POST"
echo "Expected: $EXPECTED_RESPONSE"
echo "Got: $RESPONSE"
exit 1
fi

Expand Down Expand Up @@ -82,6 +84,8 @@ jobs:
EXPECTED_RESPONSE='{"method":"POST","url":"/","clientIP":"::1","headers":{"host":"localhost:8080","user-agent":"curl/8.5.0","accept":"*/*","content-type":"application/json","content-length":"27"}}'
if [ "$RESPONSE" != "$EXPECTED_RESPONSE" ]; then
echo "Test failed: Response does not match POST body (No SSL)"
echo "Expected: $EXPECTED_RESPONSE"
echo "Got: $RESPONSE"
exit 1
fi

Expand All @@ -94,13 +98,17 @@ jobs:
id: org-name
run: echo "ORG_LC=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV


- name: Set Timestamp for use in image tag
run: echo "IMAGE_TAG=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV

- name: Build Docker image
run: |
docker build -t ghcr.io/${{ env.ORG_LC }}/headers-app:latest-dev .
docker build -t ghcr.io/${{ env.ORG_LC }}/headers-app:${{ env.IMAGE_TAG }}-latest-dev .

- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Push Docker image
run: |
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:latest-dev
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:${{ env.IMAGE_TAG }}-latest-dev
33 changes: 21 additions & 12 deletions .github/workflows/release-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
- name: Create SSL certificate and key
run: |
mkdir -p ./ssl/private
echo "${{ secrets.TEST_SSL_KEY }}" > ./ssl/private/secret.key
echo "${{ secrets.TEST_SSL_CERT }}" > ./ssl/private/cert.cer
openssl genrsa -out ./ssl/private/secret.key 2048
openssl req -new -x509 -key ./ssl/private/secret.key -out ./ssl/private/cert.cer -days 30 -subj "/CN=contoso.com"

- name: Create .env file
run: |
Expand Down Expand Up @@ -49,9 +49,11 @@ jobs:
-H "Content-Type: application/json" \
--data "$POST_BODY")
echo "Response: $RESPONSE"
EXPECTED_RESPONSE='{"method":"POST","url":"/","clientIP":"::1","headers":{"host":"localhost","user-agent":"curl/8.5.0","accept":"*/*","content-type":"application/json","content-length":"27"}}'
EXPECTED_RESPONSE='{"method":"POST","url":"/","clientIP":"::1","headers":{"host":"localhost:8443","user-agent":"curl/8.5.0","accept":"*/*","content-type":"application/json","content-length":"27"}}'
if [ "$RESPONSE" != "$EXPECTED_RESPONSE" ]; then
echo "Test failed: Response does not match POST body"
echo "Expected: $EXPECTED_RESPONSE"
echo "Got: $RESPONSE"
exit 1
fi

Expand Down Expand Up @@ -83,6 +85,8 @@ jobs:
EXPECTED_RESPONSE='{"method":"POST","url":"/","clientIP":"::1","headers":{"host":"localhost:8080","user-agent":"curl/8.5.0","accept":"*/*","content-type":"application/json","content-length":"27"}}'
if [ "$RESPONSE" != "$EXPECTED_RESPONSE" ]; then
echo "Test failed: Response does not match POST body (No SSL)"
echo "Expected: $EXPECTED_RESPONSE"
echo "Got: $RESPONSE"
exit 1
fi

Expand All @@ -91,24 +95,29 @@ jobs:
kill $(cat app.pid) || true # Kill the application using the saved PID
rm -f app.pid # Clean up the PID file

- name: Build the application
run: npm run build

- name: List build artifacts
run: ls -la ./build

- name: Set lower case org name
id: org-name
run: echo "ORG_LC=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV

- name: Set lower case release version
id: release_version
run: echo "release_version=$(echo ${{ github.ref_name }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV

- name: Build Docker image
run: |
docker build -t ghcr.io/${{ env.ORG_LC }}/headers-app:latest-dev .
docker build -t ghcr.io/${{ env.ORG_LC }}/headers-app:prod-latest -t ghcr.io/${{ env.ORG_LC }}/headers-app:prod-${{ env.release_version }} -t ghcr.io/${{ env.ORG_LC }}/headers-app:latest .

- name: Log in to GitHub Container Registry
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin

- name: Push Docker image
- name: Push Specific version Prod Docker image
run: |
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:latest-dev
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:prod-${{ env.release_version }}

- name: Push Prod-Latest Docker image
run: |
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:prod-latest

- name: Push latest Docker image
run: |
docker push ghcr.io/${{ env.ORG_LC }}/headers-app:latest
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,9 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# Ignore npm executable folders
node_modules/

# Ignore local package-lock files
package-lock.json
34 changes: 29 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ HeaderApp is a Node.js application that mirrors all request headers sent to it.
3. Run the Docker container:

```sh
docker run -p 3000:3000 headerapp
docker run -p 8080:8080 headerapp

4. The application will be running on [http://localhost:3000](http://localhost:3000)
4. The application will be running on [http://localhost:8080](http://localhost:8080)

### HTTP and HTTPS

Expand All @@ -66,7 +66,7 @@ HeaderApp is a Node.js application that mirrors all request headers sent to it.
1. Clone the repository:

```sh
git clone https://github.com/yourusername/headerapp.git
git clone https://github.com/Adal8819/headerapp.git
cd headerapp

2. Install dependencies:
Expand Down Expand Up @@ -98,7 +98,7 @@ HeaderApp is a Node.js application that mirrors all request headers sent to it.
1. Clone the repository:

```sh
git clone https://github.com/yourusername/headerapp.git
git clone https://github.com/Adal8819/headerapp.git
cd headerapp

2. Make sure that your SSL Certificates are in place. The application is designed to work with an unencrypted SSL key currently.
Expand All @@ -123,7 +123,31 @@ HeaderApp is a Node.js application that mirrors all request headers sent to it.
```sh
docker run -v 'C:/path/to/your/ssl/files:/etc/ssl/certs' -p 8080:8080 -p 8443:8443 headerapp

6. The application will be running on [http://localhost:8080](http://localhost:8080) and [https://localhost:8443](https://localhost:8443).
6. The application will be running on [http://localhost:8080](http://localhost:8080) and [https://localhost:8443](https://localhost:8443)

## Environment configuration options

Headerapp uses a .ENV file to house configurable values. There are several values that can be configured there. Below lists out the configurable values and what they control.

| Keys | Accepted Values | Definitions|
|-----------|:-----------:|:-----------|
| SSL_KEY | string | This is the path defined to the SSL private key file. Currently the application expects the key file to be stored in plain text |
| SSL_CERT | string | This is the path defined to the SSL public key file |
| USESSL | boolean | This enables or disables TLS. If this is set the SSL_KEY and SSL_CERT values must be defined. |
| PORTHTTPS | interger | This defines the HTTPS port. It is only used if the USESSL flag is set to true. If this is not set the applicatino will default to 8443. |
| PORTHTTP | interger | This defines the HTTP port. If this is not set the application will default to 8080. |
| DEBUG | boolean | This enables HTTP request debug logging to write to the console. This can be useful if you are troubleshooting what the application is seeing. |

Below is a sample .ENV file

``` text
SSL_KEY=./ssl/private/leaf.key
SSL_CERT=./ssl/private/chain.cer
USESSL=true
PORTHTTPS=8443
PORTHTTP=8080
DEBUG=true
```

## Usage

Expand Down
48 changes: 21 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import dotenv from "dotenv";
import express from "express"
import bodyParser from "body-parser";
import morgan from "morgan";
import { dirname } from "path"; // this is to handle file path
import { fileURLToPath } from "url"; // this is to handle file path
import { url } from "inspector";
Expand All @@ -26,41 +25,36 @@ function logger(req, res, next) {
next()
}

app.use(logger)
if (process.env.DEBUG === "true") {
// Log incoming requests
app.use((req, res, next) => {
console.log(`Request received: ${req.method} ${req.originalUrl}\n Client IP: ${req.ip}\n Headers: ${JSON.stringify(req.headers, null, 2)}`);
next();
});
// Log response status after the response is sent
app.use((req, res, next) => {
const originalSend = res.send;
res.send = function (body) {
const protocol = req.protocol; // 'http' or 'https'
console.log(`Response sent for ${protocol.toUpperCase()} request: ${req.method} ${req.originalUrl} with status ${res.statusCode}`);
originalSend.call(this, body);
};
next();
});
}

// use body parser middleware we can use to mess with the body.
app.use(bodyParser.urlencoded({ extended: true}));

// using Morgan middleware is a logging middleware
app.use(morgan('combined'))

// Add logging middleware to differentiate HTTP and HTTPS requests
app.use((req, res, next) => {
const protocol = req.protocol; // 'http' or 'https'
console.log(`Received a ${protocol.toUpperCase()} request: ${req.method} ${req.originalUrl}`);
next();
});

// Middleware to log response status after the response is sent
app.use((req, res, next) => {
const originalSend = res.send;
res.send = function (body) {
const protocol = req.protocol; // 'http' or 'https'
console.log(`Response sent for ${protocol.toUpperCase()} request: ${req.method} ${req.originalUrl} with status ${res.statusCode}`);
originalSend.call(this, body);
};
next();
});

// handling GET /headers request
app.get("/", (req, res) => {
res.json({
method: req.method,
url: req.originalUrl,
clientIP: req.ip,
headers: req.headers
})
})
});
});

// handling POST /headers request
app.post("/", (req, res) => {
Expand All @@ -69,8 +63,8 @@ app.post("/", (req, res) => {
url: req.originalUrl,
clientIP: req.ip,
headers: req.headers
})
})
});
});

// Create HTTP server
const httpServer = http.createServer(app);
Expand Down