Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 17 additions & 17 deletions test/certs/server.crt
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDEDCCAfgCAQEwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMxCzAJBgNV
BAgMAldBMREwDwYDVQQHDAhCZWxsZXZ1ZTEPMA0GA1UECgwGR29vZ2xlMQ4wDAYD
VQQLDAVDbG91ZDAeFw0yNTEwMTQxNjMzMTNaFw0zNTEwMTIxNjMzMTNaME4xCzAJ
BgNVBAYTAlVTMQswCQYDVQQIDAJXQTERMA8GA1UEBwwIQmVsbGV2dWUxDzANBgNV
BAoMBkdvb2dsZTEOMAwGA1UECwwFQ2xvdWQwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCpmjJqERR7zxw/Jcn+JkFxeFD+8vrKgjWDYUrIDUeFctv1trYC
yiz7T3ffF8Pavir322KV22haf/O0r4AO3ZJI3oQcwitB/o9BzvwKK4UcQlHhOTas
RxMF4gE7VyNLJv4tWM6SCOX58kCLpFEq6HyyP4UNdzxQX1+ZcsljVw+cYpbC0PjD
kIhc0fsGFcNdEtO31KpBVYeSpIMNmSIWyN7RESW6NkVvuV1Dwfw8P4n6llyNaVK/
bKJsX8XeMFEZ3q7hbTsOVCoCuiEgdR3HYsSLx16aKaRfFZzXoQg7Osyct3VApRUy
drfcqEbh0b+xKxB+sW56hC42Zl0/Q52QPDEZAgMBAAEwDQYJKoZIhvcNAQELBQAD
ggEBAEZNCifdR2DZ29H4xp+Dkza7JiT1SbddGEIn2iXdFPfFGvRL68LTFr2hZkf+
ga8HwRtxVvktvX41byzjjYoz5ALJ75UvHKw1Q/yqS08HwODNyMzRdROFGr6UzLtj
GGfYnzUhmUUKBTNF3GHSxZRsARtMnH38lNfRJ5xXXjWa18VyKXAFA6CKWRD+1ey8
/ehZX7BHZGZpSb/PLEEa3PRZMb9rAjk+pFNOrCF1QEkxJ+ZlYmRWTcpuxinPuY+8
5y5FyRYObGYzXxdFotxrc9Jg6orT5YhDW8hORWMs1cHQKyKIiqZpiS53rK+4+uYR
1IlO4QjunTe6r3xRt8G2ef47VGg=
MIIDJTCCAg2gAwIBAgIUCHJi6SkNut17iBSU+6zwrzsTwHwwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI2MDQxMjAwNTkyNFoXDTM2MDQw
OTAwNTkyNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAy4X8/+UjtlhXxHzHr34HWQmSNeHR9FL7RUvsDxlZZ6VL
TMC1hCXUO0iKmBigtgQ54jJ9753T5yMmDGk4mTU33acoYm3d/EHhxMv4Pu2o0R0Q
yhU6HStxcCACBOI7Kehuy0ZDFf2YiIsZHMTLZvfBKuZP9LtPmaDrOSV+cXaEsvnc
CCaB855HprGFE3fukslCQ8sPM8xudRF0raj5hL1/aAMbKaGtaBEc1tj2k3GlArBw
Uu89qZeC77MSmlDxoFWpcEbMZ7lPzYAoC6vMIHHBCuHXvJUudIPIdZseYE57aW+5
jyBQ/6kRZSpOSyvhIOovFmjNnSSio+/IsXQX3UrLDQIDAQABo28wbTAdBgNVHQ4E
FgQUGh54PJnDeLmHtM5N27Pl+pvtIg0wHwYDVR0jBBgwFoAUGh54PJnDeLmHtM5N
27Pl+pvtIg0wDwYDVR0TAQH/BAUwAwEB/zAaBgNVHREEEzARgglsb2NhbGhvc3SH
BH8AAAEwDQYJKoZIhvcNAQELBQADggEBACoXlufc6bCHtuGEfKw9+x9b4ZiZrNX+
rIDS4+tzq0SkbRF9naNepUfNU3Z0cx+kTDvTmH8bjBRxm2YORLUOot/mtrsI6hrK
poCcSrJA15STe2ftvNVlft9v4xPswzusWrsxTZ2oS5C1ys1UbOjFTb2qCkeYEjBw
4dfl/0lat9x9XRbfYBCWCdFo5izRhGXbgtBAl25fkEyKG7bz8q6zWFKm0xw8978U
kCKz2laAcuETBm1jCuVEd3OHAlv2/7vDKH2PpOvKwtWe2kBhILnjuDsa5LyzNJDR
ECVpOnoxrGGd8c2ezkbfH5r55aFRjFWNivt6cdbXpAgU+iqE8fISlmA=
-----END CERTIFICATE-----
52 changes: 26 additions & 26 deletions test/certs/server.key
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCpmjJqERR7zxw/
Jcn+JkFxeFD+8vrKgjWDYUrIDUeFctv1trYCyiz7T3ffF8Pavir322KV22haf/O0
r4AO3ZJI3oQcwitB/o9BzvwKK4UcQlHhOTasRxMF4gE7VyNLJv4tWM6SCOX58kCL
pFEq6HyyP4UNdzxQX1+ZcsljVw+cYpbC0PjDkIhc0fsGFcNdEtO31KpBVYeSpIMN
mSIWyN7RESW6NkVvuV1Dwfw8P4n6llyNaVK/bKJsX8XeMFEZ3q7hbTsOVCoCuiEg
dR3HYsSLx16aKaRfFZzXoQg7Osyct3VApRUydrfcqEbh0b+xKxB+sW56hC42Zl0/
Q52QPDEZAgMBAAECggEAHeOIPev7paQGsNQ6iDj6sIIJGBz++IBA6QHU2XOJpqlq
vR8xbUVu7uz+zYiVIfAAh4SYl5s+hTBmZPHGyhffJ0tbkevgDrXLTkgpX6tyvlur
rVrVWT//SLqfB/Ofyyc4hQpRAShjSwyXtmRDT6IAE7OhAZIBRZLBOLwjZIfbvu3R
e3uDzeqVq0MsiJiQIzrjMIfvtVFd35TjsfdHNv88jWGnysy8Xc95JIXeTaWSzXaL
+VNGqQnXDOFKuI6vHCfCwtTAuWQqb0K7oHBMxXRHrfRH8p/zFeTuiKYwvFgGq9qm
omQa476QHA0JZ6O196uEZGGKQfhU8lvLLm+d5tjkWQKBgQDTZ228nuHk/Xv6KiJg
YC8y68y2JyWV0i9w3vu0vrT6fnXg6t+FOrc+Mc9I6hmVFG/C+o0bKywIXaiQcCeQ
hxz/l1S5UpNVYqe55jWVIxdNcxMZooiKgzR/CLaFh+yrOuQlsU1x7Ym8CFMXINLB
cbb/efojCQzsc0LOr8IX3ehMNQKBgQDNYVP6jqWJkGnsbX+C9HzncKxfIjh5S3N6
5RqRvqZCqte1zKJR/P/tkyDMIoGffqQzro+/IAFtog2QKAmrHA1kiM0v82QYGTxU
6kExBvO+EKuJ046qb8RWD/pRK8Hx0VUtsK9Z8wDTNWzh5NAZiUPEPVEnNquDiLdr
+jQwyBDF1QKBgQCFWEX1pdoi0Gj1AMKyO7lJy0ZS1xp0CCH4dg4akfgh0MaV2lCm
/sQ6rLxs54y/Ziagu91pd6/MjxcWFEhAd5ko9tFwG8/nGdVmAvllWr8GEUHI96Zc
iCoCvwIx8+yqjPj/dXi+FfC89BtFCWUms42UU+IdW0YVlxZavK4W09gEyQKBgQCL
otbEDeRCqWs7Eh+V28BoYtTvQYcAAOqc7dOor+S+gwVyV5UtBUTENDoiUHutAx+E
+/RDz/DopzttfatFKSd56QEIzwSI1e+NFFAKk115JkBazvm6q47jrK1WLtgIH3k4
PV6bW3p+H17OHxHVqtvmOoJIlQT7wyJiSZTebcfpmQKBgQDNIkhkoH8CEgK4ecbe
Q3CoWALKYc82b5y1Dnej2ZehKG+ImDz50NIupotqZeaMQiu2NtQGLyYTgOekVFnu
AcLXsQAYVvTzPid1JDOic6tAuSGgcY/OuXnZc9/rBrOsL/xteJmJCaeFNjLKl1JM
rdhCOgf3FSzPy3+PzriASBICTw==
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLhfz/5SO2WFfE
fMevfgdZCZI14dH0UvtFS+wPGVlnpUtMwLWEJdQ7SIqYGKC2BDniMn3vndPnIyYM
aTiZNTfdpyhibd38QeHEy/g+7ajRHRDKFTodK3FwIAIE4jsp6G7LRkMV/ZiIixkc
xMtm98Eq5k/0u0+ZoOs5JX5xdoSy+dwIJoHznkemsYUTd+6SyUJDyw8zzG51EXSt
qPmEvX9oAxspoa1oERzW2PaTcaUCsHBS7z2pl4LvsxKaUPGgValwRsxnuU/NgCgL
q8wgccEK4de8lS50g8h1mx5gTntpb7mPIFD/qRFlKk5LK+Eg6i8WaM2dJKKj78ix
dBfdSssNAgMBAAECggEAH1y3Xut9dFTquXGNB+MA2NybtkflJaQ/6i7H4o/CcjFL
iDlN/14g9T25dbSd106RaOTk+S61/7Ev5Mu2GA3WXQasN3a8tWmlk8DmsTPIRukW
tD1PJj2SjnewN/ZwrYWOxS4/mjzo62mb5g4BVg2pq6Wv/oN6wa7FcJnxgSSFUFrg
DpUhecBXTSLHMisls2Oyn90g2NcKbvuxjPxet1F9+Swa0wU1kjr9u9ecElTkO4yg
Qjy34rQmEX0h7T5F2OPiPpoYS/78dVP7c5vCKDWp7QT7Z4P7DgIyXRXtLEsrfQpp
EAWU75B2ypwfqPY1zAw2ijfR5Z5Fl3DV8ZjLD5j2QQKBgQDlvsXTYlVklzYBkZIz
ZFBuP0Op7QjrRLJ0OfZTTRUUlccfpk1JvNIP9PCcteilBMpYIayUN7UzVpp8Qybn
vmrgGD3nBpE4E0v6iuM6l9rq/TmqUqUOt6nqmOWwUw/e9FBOLZ7jhGYQ4MkYANTG
MkOZ+i0l6MnGurvcCPEM2iaR0QKBgQDiyBfAUJk9+bSkXHK50w2gcYk6Yvrkp8mH
v3fY2OxYZqamvhz8lqyIpAWbJAGlqXb4Gp/RB4TA3eNk+fNiPsCNNCHEGAr0gnM5
9baaGjLbKBKu71CdA1CkkO7dQJ5PMDOExQjx2bo8It02dzYbW0vk32/Yin/WhNXL
L8F2BqoYfQKBgQC+XCnSEmIq7NeEyTdYeb/i+Wx5ObvwJIWwo+4j63SSD+BjqwnT
FS8ApbVQQ7G2OZfnGk/Cp73uAc4TNBjiX/ZyI+P2roxY6DRGLhpFDFoJ5zOGmt/E
qA2UIof+Z3R5CfoYLNjAL43aYkZ9KwMiDbfRt2b9SDsX/NV3ZblFKuRWYQKBgGlU
dCufg71USEF6qtKCIzcc5JbYuB0RjTnehSSThBp++vJBJKdwuAvy2qO28ojmD9qm
SwpECrWlmWMh8Jf1+2raBsDURepQ2IHYDQrAFlTR5POZNYDntEHrCvZ6d8zh31vQ
RBpIfQZHTyVn8xp7qeFQodsaYMvbAI2RzbIq4D/lAoGAcAGtnnCta3vsqInMICOP
cgElgTgrBvcCYOQAwMZimhwl6gJjmm0PXEAplHK0BIeO4Xu18ZjvIN/pJynToo9W
bvpgh3W9P9LkVdkaHEr9zlSvhAGE80NNjUeO3Ur7GonkclwNXwpbET/Qiv594Osn
gm6J9stVFd5jicl3SyYh5iw=
-----END PRIVATE KEY-----
186 changes: 162 additions & 24 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import fs from 'node:fs';
import https from 'node:https';
import process from 'node:process';
import express from 'express';
import { describe, it } from 'mocha';
import request from 'supertest';
import yes from '../lib/index.js';

process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
const TEST_SERVER_CERT = fs.readFileSync('./test/certs/server.crt');

describe('yes', () => {
it('should perform the 301 for an http request', (done) => {
Expand Down Expand Up @@ -40,16 +39,15 @@ describe('yes', () => {

// Verify the request returns the right header when using https
const server = createSecureServer(app);
request('https://localhost:8443')
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', 'max-age=86400; includeSubDomains')
.expect(200)
.end((error) => {
if (error) {
throw error;
}

server.close();
done();
});
}).timeout(60_000);
Expand All @@ -66,16 +64,15 @@ describe('yes', () => {
});

const server = createSecureServer(app);
request('https://localhost:8443')
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', 'max-age=86400')
.expect(200)
.end((error) => {
if (error) {
throw error;
}

server.close();
done();
});
}).timeout(60_000);
Expand All @@ -92,16 +89,15 @@ describe('yes', () => {
});

const server = createSecureServer(app);
request('https://localhost:8443')
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', 'max-age=86400')
.expect(200)
.end((error) => {
if (error) {
throw error;
}

server.close();
done();
});
}).timeout(60_000);
Expand Down Expand Up @@ -131,20 +127,162 @@ describe('yes', () => {
done();
});
});

it('should include preload when configured', (done) => {
const app = express();
app.use(yes({ preload: true }));
app.get('/test', (_request, response) => {
response.sendStatus(200);
});

const server = createSecureServer(app);
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect(
'Strict-Transport-Security',
'max-age=86400; includeSubDomains; preload',
)
.expect(200)
.end((error) => {
if (error) {
throw error;
}
done();
});
}).timeout(60_000);

it('should omit includeSubDomains when disabled', (done) => {
const app = express();
app.use(yes({ includeSubDomains: false }));
app.get('/test', (_request, response) => {
response.sendStatus(200);
});

const server = createSecureServer(app);
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', 'max-age=86400')
.expect(200)
.end((error) => {
if (error) {
throw error;
}
done();
});
}).timeout(60_000);

it('should include includeSubDomains when explicitly enabled', (done) => {
const app = express();
app.use(yes({ includeSubDomains: true }));
app.get('/test', (_request, response) => {
response.sendStatus(200);
});

const server = createSecureServer(app);
request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', 'max-age=86400; includeSubDomains')
.expect(200)
.end((error) => {
if (error) {
throw error;
}
done();
});
}).timeout(60_000);

describe('includeSubDomains', () => {
it('should include the directive by default over a secure connection', () => {
return expectSecureHeader({}, 'max-age=86400; includeSubDomains');
});

it('should include the directive when explicitly enabled over a secure connection', () => {
return expectSecureHeader(
{ includeSubDomains: true },
'max-age=86400; includeSubDomains',
);
});

it('should omit the directive when disabled over a secure connection', () => {
return expectSecureHeader({ includeSubDomains: false }, 'max-age=86400');
});

it('should compose correctly with preload and maxAge when enabled', () => {
return expectSecureHeader(
{ includeSubDomains: true, preload: true, maxAge: 31_536_000 },
'max-age=31536000; includeSubDomains; preload',
);
});

it('should compose correctly with preload and maxAge when disabled', () => {
return expectSecureHeader(
{ includeSubDomains: false, preload: true, maxAge: 31_536_000 },
'max-age=31536000; preload',
);
});

it('should include the directive by default for forwarded https requests', () => {
return expectForwardedSecureHeader(
{},
'max-age=86400; includeSubDomains',
);
});

it('should honor an explicit true value for forwarded https requests', () => {
return expectForwardedSecureHeader(
{ includeSubDomains: true },
'max-age=86400; includeSubDomains',
);
});

it('should honor an explicit false value for forwarded https requests', () => {
return expectForwardedSecureHeader(
{ includeSubDomains: false },
'max-age=86400',
);
});
});
});

function createSecureServer(app) {
// Server the app over https
return https
.createServer(
{
key: fs.readFileSync('./test/certs/server.key'),
cert: fs.readFileSync('./test/certs/server.crt'),
ca: fs.readFileSync('./test/certs/ca.crt'),
requestCert: true,
rejectUnauthorized: false,
},
app,
)
.listen('8443');
return https.createServer(
{
key: fs.readFileSync('./test/certs/server.key'),
cert: fs.readFileSync('./test/certs/server.crt'),
},
app,
);
}

function expectSecureHeader(options, expectedHeader) {
const app = express();
app.use(yes(options));
app.get('/test', (_request, response) => {
response.sendStatus(200);
});

const server = createSecureServer(app);
return request(server)
.get('/test')
.ca(TEST_SERVER_CERT)
.expect('Strict-Transport-Security', expectedHeader)
.expect(200);
}

function expectForwardedSecureHeader(options, expectedHeader) {
const app = express();
app.use(yes(options));
app.get('/test', (_request, response) => {
response.sendStatus(200);
});

return request(app)
.get('/test')
.set('X-Forwarded-Proto', 'https')
.set('Host', 'example.com')
.expect('Strict-Transport-Security', expectedHeader)
.expect(200);
}
Loading