Compare commits
34 Commits
Author | SHA1 | Date |
---|---|---|
Jake Howard | b86b542998 | |
Jake Howard | 3caa4a51db | |
Jake Howard | 0d311ac19c | |
Jake Howard | a90feaffdf | |
Jake Howard | ee45331b4d | |
Jake Howard | 0c763cafd3 | |
Jake Howard | 0ec819e232 | |
Jake Howard | c74f486b7e | |
Jake Howard | cc5d07595b | |
Jake Howard | c9004a8be5 | |
Jake Howard | 18c4ae38a0 | |
Jake Howard | d8ba44143d | |
Jake Howard | 3232eba22a | |
Jake Howard | 25c973303d | |
Jake Howard | 2e2e4c8b8f | |
Jake Howard | e53846e71f | |
Jake Howard | 28b1c4f51c | |
Jake Howard | c35760d95e | |
Jake Howard | 28eec3e28c | |
Jake Howard | 38dcc3e5fa | |
Jake Howard | b86ce01aa2 | |
Jake Howard | ac29b7f932 | |
Jake Howard | 45904be707 | |
Jake Howard | 5d5f69c79e | |
Jake Howard | 92a4fc3cda | |
Jake Howard | 08a15c97ab | |
Jake Howard | bdcff47ba4 | |
Jake Howard | 44c64d4f05 | |
Jake Howard | fb7764b3c7 | |
Jake Howard | e16075a702 | |
Jake Howard | 42f5af27f0 | |
Jake Howard | 251d46b43f | |
Jake Howard | ef9b100dd1 | |
Jake Howard | e3d5406d27 |
|
@ -0,0 +1,21 @@
|
|||
version: 2.0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
- image: circleci/node:8
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Install dependencies
|
||||
command: npm install
|
||||
- run:
|
||||
name: Build Project
|
||||
command: npm run build
|
||||
- run:
|
||||
name: Run Tests
|
||||
command: npm test
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build docker container
|
||||
command: docker build .
|
|
@ -0,0 +1,27 @@
|
|||
FROM node:8-alpine
|
||||
|
||||
COPY ./src /opt/tstatic/src
|
||||
COPY ./package.json opt/tstatic/package.json
|
||||
COPY ./package-lock.json opt/tstatic/package-lock.json
|
||||
COPY ./tsconfig.json opt/tstatic/tsconfig.json
|
||||
COPY ./site /var/www
|
||||
|
||||
WORKDIR /opt/tstatic
|
||||
|
||||
RUN apk add --no-cache git
|
||||
|
||||
RUN npm install
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN npm run build
|
||||
|
||||
RUN npm prune --production
|
||||
|
||||
RUN npm install -g .
|
||||
|
||||
WORKDIR /
|
||||
|
||||
CMD tstatic /var/www
|
||||
|
||||
EXPOSE 5000
|
27
README.md
27
README.md
|
@ -7,12 +7,10 @@
|
|||
The only static-file server you'll ever need!
|
||||
|
||||
### Features:
|
||||
- Logging - [`winston`](https://www.npmjs.com/package/winston)
|
||||
- Basic-Auth - [`basic-auth`](https://www.npmjs.com/package/basic-auth)
|
||||
- Custom 404 page
|
||||
- Optimum Compression - [`compression`](https://www.npmjs.com/package/compression)
|
||||
- Security checks / headers - [`helmet`](https://www.npmjs.com/package/helmet)
|
||||
- Opbeat error-reporting - [docs](https://opbeat.com/docs/articles/get-started-with-express/)
|
||||
- Whitelist IP Addresses - [`express-ip-access-control`](https://www.npmjs.com/package/express-ip-access-control)
|
||||
- Directory Listing - [`serve-index`](https://www.npmjs.com/package/serve-index)
|
||||
|
||||
|
@ -26,7 +24,6 @@ The only static-file server you'll ever need!
|
|||
-b <auth> --basic-auth=<auth> Enable basic-auth.
|
||||
-i <ips> --ips=<ips> Allowed IP addresses.
|
||||
-l --list-dir List Directory.
|
||||
--opbeat Enable Opbeat.
|
||||
-o --open Open in browser after start.
|
||||
```
|
||||
`dir` is where your static files are.
|
||||
|
@ -40,7 +37,7 @@ The only static-file server you'll ever need!
|
|||
The port for the server to listen on. Currently supports plain HTTP only
|
||||
|
||||
##### `basic-auth`
|
||||
Enable basic-auth for all paths. Currently only supports single credentals.
|
||||
Enable basic-auth for all paths. Currently only supports single credentals.
|
||||
|
||||
Format:`-b username:password`
|
||||
|
||||
|
@ -52,8 +49,24 @@ Format: `-i 192.168.1.100,192.168.1.101`
|
|||
##### `list-dir`
|
||||
Enables directory listing. Allow browseing
|
||||
|
||||
##### `opbeat`
|
||||
Enable opbeat error reporting. `--opbeat` only enables this, configuration is done using [environment varables](https://opbeat.com/docs/articles/get-started-with-express/#appId).
|
||||
|
||||
##### `open`
|
||||
Open the server in the browser one started. It will open in your default browser, and use url `http://0.0.0.0:<port>`.
|
||||
|
||||
### Docker
|
||||
Included in this repo is a `Dockerfile` to use. The default setup requires being run from the project directory, and will serve `/var/www` in the container on port `5000`. By default, this directory is contains a simple index file, however can be overriden.
|
||||
|
||||
Below is an example `docker-compose.yml` file you can use with it:
|
||||
|
||||
```yml
|
||||
version: "2"
|
||||
services:
|
||||
tstatic:
|
||||
image: "tstatic"
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
volumes:
|
||||
- ./site/:/var/www
|
||||
ports:
|
||||
- "5000:5000"
|
||||
```
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
machine:
|
||||
node:
|
||||
version: 6.11.0
|
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tstatic",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.0",
|
||||
"description": "The only static-file server you'll ever need!",
|
||||
"main": "./dist/server.js",
|
||||
"bin": {
|
||||
|
@ -8,14 +8,14 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start": "node ./dist/index.js",
|
||||
"prepublish": "typings install && npm run build",
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "tsc",
|
||||
"test": "npm run build && npm run lint && npm run mocha && nsp check",
|
||||
"mocha": "mocha --compilers ts:ts-node/register --require scripts/test-helper.js --recursive --bail tests/**/*.test.ts tests/*.test.ts",
|
||||
"lint": "tslint src/**/*.ts --type-check --project tsconfig.json"
|
||||
"test": "npm run lint && npm run mocha",
|
||||
"mocha": "mocha --require scripts/test-helper.js --recursive --bail tests/**/*.test.ts tests/*.test.ts",
|
||||
"lint": "tslint src/**/*.ts --project tsconfig.json"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.9.4"
|
||||
"node": "8"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -27,29 +27,36 @@
|
|||
},
|
||||
"homepage": "https://github.com/RealOrangeOne/tstatic#readme",
|
||||
"dependencies": {
|
||||
"compression": "1.6.2",
|
||||
"connect-static-file": "1.2.0",
|
||||
"compression": "1.7.2",
|
||||
"connect-static-file": "2.0.0",
|
||||
"docopt": "0.6.2",
|
||||
"express": "4.15.3",
|
||||
"express-basic-auth": "1.0.1",
|
||||
"express": "4.16.3",
|
||||
"express-basic-auth": "1.1.4",
|
||||
"express-ip-access-control": "1.0.5",
|
||||
"express-winston": "2.4.0",
|
||||
"helmet": "3.6.1",
|
||||
"opbeat": "4.14.0",
|
||||
"helmet": "3.12.0",
|
||||
"morgan": "1.9.0",
|
||||
"open": "0.0.5",
|
||||
"serve-index": "1.9.0",
|
||||
"winston": "2.3.1"
|
||||
"serve-index": "1.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "4.0.2",
|
||||
"@types/docopt": "0.6.31",
|
||||
"@types/node-fetch": "1.6.7",
|
||||
"@types/open": "0.0.29",
|
||||
"@types/chai": "4.1.2",
|
||||
"@types/compression": "0.0.35",
|
||||
"@types/express": "4.11.1",
|
||||
"@types/helmet": "0.0.37",
|
||||
"@types/mocha": "2.2.48",
|
||||
"@types/morgan": "1.7.35",
|
||||
"@types/serve-index": "1.7.29",
|
||||
"chai": "4.1.2",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"mocha": "3.4.2",
|
||||
"node-fetch": "1.7.1",
|
||||
"nsp": "2.6.3",
|
||||
"mocha": "5.0.4",
|
||||
"node-fetch": "2.1.1",
|
||||
"supertest": "3.0.0",
|
||||
"ts-node": "3.2.0",
|
||||
"tslint": "5.5.0",
|
||||
"typescript": "2.2.1",
|
||||
"typings": "2.1.0"
|
||||
"ts-node": "5.0.1",
|
||||
"tslint": "5.9.1",
|
||||
"tslint-config-dabapps": "dabapps/tslint-config-dabapps#v0.3.0",
|
||||
"typescript": "2.7.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require('ts-node/register');
|
||||
|
||||
const chai = require('chai');
|
||||
const chaiAsPromised = require('chai-as-promised');
|
||||
|
||||
|
|
|
@ -2,24 +2,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Oops!</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
width: 75%;
|
||||
padding-top: 50px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
font-family: "Trebuchet MS", Helvetica, Arial, sans-serif;
|
||||
font-size: 80%;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 30px 0;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Something's not right!</h1>
|
||||
<p><strong>Sorry!</strong> Something has gone wrong while handling your request. Please try again later.</p>
|
||||
<h1>TStatic File Server</h1>
|
||||
<p>Add some content to your serve directory to get started</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
body {
|
||||
width: 75%;
|
||||
padding-top: 50px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
font-family: "Trebuchet MS", Helvetica, Arial, sans-serif;
|
||||
font-size: 80%;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 30px 0;
|
||||
}
|
10
src/cli.ts
10
src/cli.ts
|
@ -1,5 +1,5 @@
|
|||
import { docopt } from 'docopt';
|
||||
import { Options } from './types';
|
||||
import { IOptions } from './types';
|
||||
|
||||
const PKG = require('../package.json');
|
||||
|
||||
|
@ -19,11 +19,11 @@ Options:
|
|||
-b <auth> --basic-auth=<auth> Enable basic-auth.
|
||||
-i <ips> --ips=<ips> Allowed IP addresses.
|
||||
-l --list-dir List Directory.
|
||||
--opbeat Enable Opbeat.
|
||||
-s --allow-http Allow connection over HTTP.
|
||||
-o --open Open in browser after start.
|
||||
`;
|
||||
|
||||
export default function getArgs() : Options {
|
||||
export default function getArgs() : IOptions {
|
||||
const rawArgs = docopt(ARG_DATA, {
|
||||
version: PKG.version,
|
||||
help: true
|
||||
|
@ -34,7 +34,7 @@ export default function getArgs() : Options {
|
|||
basicAuth: rawArgs['--basic-auth'] ? rawArgs['--basic-auth'].split(':') : [],
|
||||
dirList: rawArgs['--list-dir'],
|
||||
serveDir: rawArgs['<dir>'],
|
||||
opbeat: rawArgs['--opbeat'],
|
||||
open: rawArgs['--open']
|
||||
open: rawArgs['--open'],
|
||||
allowHttp: rawArgs['--allow-http']
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { docopt } from 'docopt';
|
||||
import createServer from './server';
|
||||
import getArgs from './cli';
|
||||
import * as open from 'open';
|
||||
import open from 'open';
|
||||
|
||||
const ARGS = getArgs();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as path from 'path';
|
|||
|
||||
export default function handle404(serveDir: string) {
|
||||
const handle404Middleware = staticFile(path.join(serveDir, '.404.html'));
|
||||
return function(request: Request, response: Response, next: () => void) {
|
||||
return (request: Request, response: Response, next: () => void) => {
|
||||
response.statusCode = 404;
|
||||
return handle404Middleware(request, response, next);
|
||||
};
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import * as expressWinston from 'express-winston';
|
||||
import * as winston from 'winston';
|
||||
|
||||
export default expressWinston.logger({
|
||||
colorize: true,
|
||||
meta: false,
|
||||
msg: '{{ req.url }} '
|
||||
.concat('status:{{ res.statusCode }} ')
|
||||
.concat('useragent:{{ req.headers["user-agent"] }} ')
|
||||
.concat('time:{{ res.responseTime }}ms'),
|
||||
statusLevels: true,
|
||||
transports: [
|
||||
new winston.transports.Console({
|
||||
colorize: true
|
||||
})
|
||||
],
|
||||
});
|
|
@ -3,39 +3,34 @@ import * as express from 'express';
|
|||
import * as AccessControl from 'express-ip-access-control';
|
||||
import * as compression from 'compression';
|
||||
import * as helmet from 'helmet';
|
||||
import * as opbeat from 'opbeat';
|
||||
import * as expectCt from 'expect-ct';
|
||||
import * as referrerPolicy from 'referrer-policy';
|
||||
import * as morgan from 'morgan';
|
||||
|
||||
|
||||
import logging from './middleware/logging';
|
||||
import basicAuthHandler from './middleware/basic-auth';
|
||||
import { serveIndexHandle, indexHandle, staticFileHandle } from './middleware/static-files';
|
||||
import handle404 from './middleware/404';
|
||||
|
||||
import { Options } from './types';
|
||||
import { IOptions } from './types';
|
||||
|
||||
const PKG = require('../package.json');
|
||||
|
||||
export default function createServer(opts : Options) : express.Application {
|
||||
export default function createServer(opts : IOptions) : express.Application {
|
||||
const app = express();
|
||||
|
||||
app.use(helmet());
|
||||
app.use(helmet.hidePoweredBy({setTo: `tstatic ${PKG.version}`}));
|
||||
app.use(helmet.ieNoOpen());
|
||||
app.use(helmet.noCache());
|
||||
app.use(helmet({
|
||||
hsts: {
|
||||
maxAge: 5184000,
|
||||
setIf: () => !opts.allowHttp,
|
||||
includeSubdomains: false
|
||||
},
|
||||
noCache: true,
|
||||
expectCt: {
|
||||
enforce: false,
|
||||
maxAge: 1000
|
||||
}
|
||||
}));
|
||||
app.use(referrerPolicy({ policy: 'same-origin' }));
|
||||
app.use(expectCt({
|
||||
enforce: false,
|
||||
maxAge: 1000
|
||||
}));
|
||||
app.use(helmet.hsts({
|
||||
maxAge: 5184000,
|
||||
setIf: (req, res) => req.secure,
|
||||
}));
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.use(logging);
|
||||
app.use(morgan('combined'));
|
||||
}
|
||||
|
||||
if (opts.allowed_ips.length) {
|
||||
|
@ -61,11 +56,6 @@ export default function createServer(opts : Options) : express.Application {
|
|||
app.use(handle404(opts.serveDir));
|
||||
|
||||
app.use(compression({ level: 9 }));
|
||||
if (opts.opbeat) {
|
||||
app.use(opbeat.start({
|
||||
active: opts.opbeat
|
||||
}).middleware.express());
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,5 @@
|
|||
declare module 'express-ip-access-control';
|
||||
declare module 'connect-static-file';
|
||||
declare module 'express-basic-auth';
|
||||
declare module 'winston'; // doesnt like console transport
|
||||
declare module 'express-winston';
|
||||
declare module 'opbeat';
|
||||
declare module 'docopt';
|
||||
declare module 'open';
|
||||
declare module 'node-fetch';
|
||||
declare module 'chai';
|
||||
declare module 'expect-ct';
|
||||
declare module 'referrer-policy';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
export interface Options {
|
||||
export interface IOptions {
|
||||
port: number;
|
||||
allowed_ips: string[];
|
||||
basicAuth: string[];
|
||||
dirList: boolean;
|
||||
serveDir: string;
|
||||
opbeat: boolean;
|
||||
open: boolean;
|
||||
allowHttp: boolean;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import createServer from '../src/server';
|
||||
import { Options } from '../src/types';
|
||||
import { IOptions } from '../src/types';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
|
||||
export function runServer(opts: Object, url : string, callback: Function) {
|
||||
const app = createServer(opts as Options);
|
||||
const app = createServer(opts as IOptions);
|
||||
const server = app.listen(1234, function () {
|
||||
return fetch('http://0.0.0.0:1234' + url).then(function (response : any) {
|
||||
server.close();
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import { expect } from 'chai';
|
||||
import { runServer } from '../helpers';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { IOptions } from '../../src/types';
|
||||
|
||||
|
||||
describe('Static Files', function () {
|
||||
const body = fs.readFileSync(path.join(__dirname, '../..', 'site', 'index.html')).toString();
|
||||
const cssBody = fs.readFileSync(path.join(__dirname, '../..', 'site', 'style.css')).toString();
|
||||
|
||||
describe('index route', function () {
|
||||
|
||||
['', '/', '/index.html'].forEach(function (path : string) {
|
||||
it('should render ' + path, function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, path, function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.equal(body).notify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should return static files', function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, '/style.css', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.equal(cssBody).notify(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Directory listing', function () {
|
||||
const SERVER_CONFIG = {
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: true,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
} as IOptions;
|
||||
|
||||
it('Should allow directory listing', function (done) {
|
||||
runServer(SERVER_CONFIG, '/', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.not.equal(body).notify(done);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should show index file in directory listing', function (done) {
|
||||
runServer(SERVER_CONFIG, '/', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.contain('style.css').notify(done);
|
||||
});
|
||||
});
|
||||
it('Should show css file in directory listing', function (done) {
|
||||
runServer(SERVER_CONFIG, '/', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.contain('index.html').notify(done);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -2,7 +2,7 @@ import { expect } from 'chai';
|
|||
import { runServer } from './helpers';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Options } from '../src/types';
|
||||
import { IOptions } from '../src/types';
|
||||
|
||||
const PKG = require('../package.json');
|
||||
|
||||
|
@ -22,26 +22,6 @@ describe('Server', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('index route', function () {
|
||||
const body = fs.readFileSync(path.join(__dirname, '..', 'site', 'index.html')).toString();
|
||||
|
||||
['', '/', '/index.html'].forEach(function (path : string) {
|
||||
it('should render ' + path, function (done) {
|
||||
runServer({
|
||||
allowed_ips: [],
|
||||
basicAuth: [],
|
||||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
}, path, function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.text()).to.eventually.equal(body).notify(done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('secure headers', function () {
|
||||
const SERVER_SETTINGS = {
|
||||
allowed_ips: [],
|
||||
|
@ -49,14 +29,14 @@ describe('Server', function () {
|
|||
dirList: false,
|
||||
serveDir: 'site/',
|
||||
opbeat: false,
|
||||
open: false
|
||||
} as Options;
|
||||
open: false,
|
||||
allowHttp: false
|
||||
} as IOptions;
|
||||
|
||||
it('Should have no powered by header', function (done) {
|
||||
runServer(SERVER_SETTINGS, '/index.html', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.headers.get('x-powered-by')).to.contain('tstatic');
|
||||
expect(response.headers.get('x-powered-by')).to.contain(PKG.version);
|
||||
expect(response.headers.get('x-powered-by')).to.be.null;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -113,12 +93,28 @@ describe('Server', function () {
|
|||
});
|
||||
});
|
||||
|
||||
it('Should block cache', function (done) {
|
||||
it('Should block referrer transfer', function (done) {
|
||||
runServer(SERVER_SETTINGS, '/index.html', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.headers.get('referrer-policy')).to.contain('same-origin');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should have HSTS header', function (done) {
|
||||
runServer(SERVER_SETTINGS, '/index.html', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.headers.get('strict-transport-security')).to.contain('5184000');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not have HSTS header if HTTP is allowed', function (done) {
|
||||
runServer({...SERVER_SETTINGS, allowHttp: true}, '/index.html', function (response : any) {
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.headers.get('strict-transport-security')).to.be.null;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
],
|
||||
"typeRoots": [
|
||||
"node_modules",
|
||||
"typings",
|
||||
"node_modules/@types/",
|
||||
"src/types"
|
||||
],
|
||||
"compileOnSave": false
|
||||
|
|
10
tslint.json
10
tslint.json
|
@ -1,9 +1,5 @@
|
|||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rules": {
|
||||
"quotemark": [true, "single"],
|
||||
"trailing-comma": false,
|
||||
"only-arrow-functions": false,
|
||||
"interface-name": false
|
||||
}
|
||||
"extends": [
|
||||
"tslint-config-dabapps"
|
||||
]
|
||||
}
|
||||
|
|
16
typings.json
16
typings.json
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"compression": "registry:dt/compression#0.0.0+20160725212620",
|
||||
"debug": "registry:npm/debug#2.0.0+20160723033700",
|
||||
"express": "registry:npm/express#4.14.0+20160925001530",
|
||||
"helmet": "registry:dt/helmet#0.0.0+20170310054102",
|
||||
"serve-index": "registry:dt/serve-index#1.7.2+20160428043022"
|
||||
},
|
||||
"globalDependencies": {
|
||||
"node": "registry:dt/node#7.0.0+20170204020307"
|
||||
},
|
||||
"globalDevDependencies": {
|
||||
"chai": "registry:dt/chai#3.4.0+20170217154556",
|
||||
"mocha": "registry:dt/mocha#2.2.5+20170204022515"
|
||||
}
|
||||
}
|
Reference in New Issue