forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
3
Kha/Tools/khamake/node_modules/node-static/.npmignore
generated
vendored
Normal file
3
Kha/Tools/khamake/node_modules/node-static/.npmignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
npm-debug.log
|
||||
node_modules
|
||||
|
20
Kha/Tools/khamake/node_modules/node-static/LICENSE
generated
vendored
Normal file
20
Kha/Tools/khamake/node_modules/node-static/LICENSE
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2010-14 Alexis Sellier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
234
Kha/Tools/khamake/node_modules/node-static/README.md
generated
vendored
Normal file
234
Kha/Tools/khamake/node_modules/node-static/README.md
generated
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
node-static
|
||||
===========
|
||||
|
||||
> a simple, *rfc 2616 compliant* file streaming module for [node](http://nodejs.org)
|
||||
|
||||
node-static understands and supports *conditional GET* and *HEAD* requests.
|
||||
node-static was inspired by some of the other static-file serving modules out there,
|
||||
such as node-paperboy and antinode.
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
```js
|
||||
var static = require('node-static');
|
||||
|
||||
//
|
||||
// Create a node-static server instance to serve the './public' folder
|
||||
//
|
||||
var file = new static.Server('./public');
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
//
|
||||
// Serve files!
|
||||
//
|
||||
file.serve(request, response);
|
||||
}).resume();
|
||||
}).listen(8080);
|
||||
```
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
### Creating a node-static Server #
|
||||
|
||||
Creating a file server instance is as simple as:
|
||||
|
||||
```js
|
||||
new static.Server();
|
||||
```
|
||||
|
||||
This will serve files in the current directory. If you want to serve files in a specific
|
||||
directory, pass it as the first argument:
|
||||
|
||||
```js
|
||||
new static.Server('./public');
|
||||
```
|
||||
|
||||
You can also specify how long the client is supposed to cache the files node-static serves:
|
||||
|
||||
```js
|
||||
new static.Server('./public', { cache: 3600 });
|
||||
```
|
||||
|
||||
This will set the `Cache-Control` header, telling clients to cache the file for an hour.
|
||||
This is the default setting.
|
||||
|
||||
### Serving files under a directory #
|
||||
|
||||
To serve files under a directory, simply call the `serve` method on a `Server` instance, passing it
|
||||
the HTTP request and response object:
|
||||
|
||||
```js
|
||||
var static = require('node-static');
|
||||
|
||||
var fileServer = new static.Server('./public');
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
fileServer.serve(request, response);
|
||||
}).resume();
|
||||
}).listen(8080);
|
||||
```
|
||||
|
||||
### Serving specific files #
|
||||
|
||||
If you want to serve a specific file, like an error page for example, use the `serveFile` method:
|
||||
|
||||
```js
|
||||
fileServer.serveFile('/error.html', 500, {}, request, response);
|
||||
```
|
||||
|
||||
This will serve the `error.html` file, from under the file root directory, with a `500` status code.
|
||||
For example, you could serve an error page, when the initial request wasn't found:
|
||||
|
||||
```js
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
fileServer.serve(request, response, function (e, res) {
|
||||
if (e && (e.status === 404)) { // If the file wasn't found
|
||||
fileServer.serveFile('/not-found.html', 404, {}, request, response);
|
||||
}
|
||||
});
|
||||
}).resume();
|
||||
}).listen(8080);
|
||||
```
|
||||
|
||||
More on intercepting errors bellow.
|
||||
|
||||
### Intercepting errors & Listening #
|
||||
|
||||
An optional callback can be passed as last argument, it will be called every time a file
|
||||
has been served successfully, or if there was an error serving the file:
|
||||
|
||||
```js
|
||||
var static = require('node-static');
|
||||
|
||||
var fileServer = new static.Server('./public');
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
fileServer.serve(request, response, function (err, result) {
|
||||
if (err) { // There was an error serving the file
|
||||
console.error("Error serving " + request.url + " - " + err.message);
|
||||
|
||||
// Respond to the client
|
||||
response.writeHead(err.status, err.headers);
|
||||
response.end();
|
||||
}
|
||||
});
|
||||
}).resume();
|
||||
}).listen(8080);
|
||||
```
|
||||
|
||||
Note that if you pass a callback, and there is an error serving the file, node-static
|
||||
*will not* respond to the client. This gives you the opportunity to re-route the request,
|
||||
or handle it differently.
|
||||
|
||||
For example, you may want to interpret a request as a static request, but if the file isn't found,
|
||||
send it to an application.
|
||||
|
||||
If you only want to *listen* for errors, you can use *event listeners*:
|
||||
|
||||
```js
|
||||
fileServer.serve(request, response).addListener('error', function (err) {
|
||||
console.error("Error serving " + request.url + " - " + err.message);
|
||||
});
|
||||
```
|
||||
|
||||
With this method, you don't have to explicitly send the response back, in case of an error.
|
||||
|
||||
### Options when creating an instance of `Server` #
|
||||
|
||||
#### `cache` #
|
||||
|
||||
Sets the `Cache-Control` header.
|
||||
|
||||
example: `{ cache: 7200 }`
|
||||
|
||||
Passing a number will set the cache duration to that number of seconds.
|
||||
Passing `false` will disable the `Cache-Control` header.
|
||||
|
||||
> Defaults to `3600`
|
||||
|
||||
|
||||
#### `serverInfo` #
|
||||
|
||||
Sets the `Server` header.
|
||||
|
||||
example: `{ serverInfo: "myserver" }`
|
||||
|
||||
> Defaults to `node-static/{version}`
|
||||
|
||||
#### `headers` #
|
||||
|
||||
Sets response headers.
|
||||
|
||||
example: `{ 'X-Hello': 'World!' }`
|
||||
|
||||
> defaults to `{}`
|
||||
|
||||
#### `gzip` #
|
||||
|
||||
Enable support for sending compressed responses. This will enable a check for a
|
||||
file with the same name plus '.gz' in the same folder. If the compressed file is
|
||||
found and the client has indicated support for gzip file transfer, the contents
|
||||
of the .gz file will be sent in place of the uncompressed file along with a
|
||||
Content-Encoding: gzip header to inform the client the data has been compressed.
|
||||
|
||||
example: `{ gzip: true }`
|
||||
example: `{ gzip: /^\/text/ }`
|
||||
|
||||
Passing `true` will enable this check for all files.
|
||||
Passing a RegExp instance will only enable this check if the content-type of the
|
||||
respond would match that RegExp using its test() method.
|
||||
|
||||
> Defaults to `false`
|
||||
|
||||
#### `indexFile` #
|
||||
|
||||
Choose a custom index file when serving up directories.
|
||||
|
||||
example: `{ indexFile: "index.htm" }`
|
||||
|
||||
> Defaults to `index.html`
|
||||
|
||||
|
||||
Command Line Interface
|
||||
----------------------
|
||||
|
||||
`node-static` also provides a CLI.
|
||||
|
||||
### Installation #
|
||||
|
||||
```sh
|
||||
$ npm install -g node-static
|
||||
```
|
||||
|
||||
### Example Usage #
|
||||
|
||||
```sh
|
||||
# serve up the current directory
|
||||
$ static
|
||||
serving "." at http://127.0.0.1:8080
|
||||
|
||||
# serve up a different directory
|
||||
$ static public
|
||||
serving "public" at http://127.0.0.1:8080
|
||||
|
||||
# specify additional headers (this one is useful for development)
|
||||
$ static -H '{"Cache-Control": "no-cache, must-revalidate"}'
|
||||
serving "." at http://127.0.0.1:8080
|
||||
|
||||
# set cache control max age
|
||||
$ static -c 7200
|
||||
serving "." at http://127.0.0.1:8080
|
||||
|
||||
# expose the server to your local network
|
||||
$ static -a 0.0.0.0
|
||||
serving "." at http://0.0.0.0:8080
|
||||
|
||||
# show help message, including all options
|
||||
$ static -h
|
||||
```
|
43
Kha/Tools/khamake/node_modules/node-static/benchmark/node-static-0.3.0.txt
generated
vendored
Normal file
43
Kha/Tools/khamake/node_modules/node-static/benchmark/node-static-0.3.0.txt
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
|
||||
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
|
||||
Licensed to The Apache Software Foundation, http://www.apache.org/
|
||||
|
||||
Benchmarking 127.0.0.1 (be patient)
|
||||
|
||||
|
||||
Server Software: node-static/0.3.0
|
||||
Server Hostname: 127.0.0.1
|
||||
Server Port: 8080
|
||||
|
||||
Document Path: /lib/node-static.js
|
||||
Document Length: 6038 bytes
|
||||
|
||||
Concurrency Level: 20
|
||||
Time taken for tests: 2.323 seconds
|
||||
Complete requests: 10000
|
||||
Failed requests: 0
|
||||
Write errors: 0
|
||||
Total transferred: 63190000 bytes
|
||||
HTML transferred: 60380000 bytes
|
||||
Requests per second: 4304.67 [#/sec] (mean)
|
||||
Time per request: 4.646 [ms] (mean)
|
||||
Time per request: 0.232 [ms] (mean, across all concurrent requests)
|
||||
Transfer rate: 26563.66 [Kbytes/sec] received
|
||||
|
||||
Connection Times (ms)
|
||||
min mean[+/-sd] median max
|
||||
Connect: 0 0 0.2 0 3
|
||||
Processing: 1 4 1.4 4 28
|
||||
Waiting: 1 4 1.3 4 18
|
||||
Total: 2 5 1.5 4 28
|
||||
|
||||
Percentage of the requests served within a certain time (ms)
|
||||
50% 4
|
||||
66% 5
|
||||
75% 5
|
||||
80% 5
|
||||
90% 5
|
||||
95% 6
|
||||
98% 8
|
||||
99% 9
|
||||
100% 28 (longest request)
|
131
Kha/Tools/khamake/node_modules/node-static/bin/cli.js
generated
vendored
Normal file
131
Kha/Tools/khamake/node_modules/node-static/bin/cli.js
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs'),
|
||||
tty = require('tty'),
|
||||
statik = require('./../lib/node-static');
|
||||
|
||||
var argv = require('optimist')
|
||||
.usage([
|
||||
'USAGE: $0 [-p <port>] [<directory>]',
|
||||
'simple, rfc 2616 compliant file streaming module for node']
|
||||
.join('\n\n'))
|
||||
.option('port', {
|
||||
alias: 'p',
|
||||
'default': 8080,
|
||||
description: 'TCP port at which the files will be served'
|
||||
})
|
||||
.option('host-address', {
|
||||
alias: 'a',
|
||||
'default': '127.0.0.1',
|
||||
description: 'the local network interface at which to listen'
|
||||
})
|
||||
.option('cache', {
|
||||
alias: 'c',
|
||||
description: '"Cache-Control" header setting, defaults to 3600'
|
||||
})
|
||||
.option('version', {
|
||||
alias: 'v',
|
||||
description: 'node-static version'
|
||||
})
|
||||
.option('headers', {
|
||||
alias: 'H',
|
||||
description: 'additional headers (in JSON format)'
|
||||
})
|
||||
.option('header-file', {
|
||||
alias: 'f',
|
||||
description: 'JSON file of additional headers'
|
||||
})
|
||||
.option('gzip', {
|
||||
alias: 'z',
|
||||
description: 'enable compression (tries to serve file of same name plus \'.gz\')'
|
||||
})
|
||||
.option('spa', {
|
||||
description: 'serve the content as a single page app by redirecting all non-file requests to the index html file'
|
||||
})
|
||||
.option('indexFile', {
|
||||
alias: 'i',
|
||||
'default': 'index.html',
|
||||
description: 'specify a custom index file when serving up directories'
|
||||
})
|
||||
.option('help', {
|
||||
alias: 'h',
|
||||
description: 'display this help message'
|
||||
})
|
||||
.argv;
|
||||
|
||||
var dir = argv._[0] || '.';
|
||||
|
||||
var colors = require('colors');
|
||||
|
||||
var log = function(request, response, statusCode) {
|
||||
var d = new Date();
|
||||
var seconds = d.getSeconds() < 10? '0'+d.getSeconds() : d.getSeconds(),
|
||||
datestr = d.getHours() + ':' + d.getMinutes() + ':' + seconds,
|
||||
line = datestr + ' [' + response.statusCode + ']: ' + request.url,
|
||||
colorized = line;
|
||||
if (tty.isatty(process.stdout.fd))
|
||||
colorized = (response.statusCode >= 500) ? line.red.bold :
|
||||
(response.statusCode >= 400) ? line.red :
|
||||
line;
|
||||
console.log(colorized);
|
||||
};
|
||||
|
||||
var file, options;
|
||||
|
||||
if (argv.help) {
|
||||
require('optimist').showHelp(console.log);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv.version) {
|
||||
console.log('node-static', statik.version.join('.'));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv.cache) {
|
||||
(options = options || {}).cache = argv.cache;
|
||||
}
|
||||
|
||||
if (argv.headers) {
|
||||
(options = options || {}).headers = JSON.parse(argv.headers);
|
||||
}
|
||||
|
||||
if (argv['header-file']) {
|
||||
(options = options || {}).headers =
|
||||
JSON.parse(fs.readFileSync(argv['header-file']));
|
||||
}
|
||||
|
||||
if (argv.gzip) {
|
||||
(options = options || {}).gzip = true;
|
||||
}
|
||||
|
||||
if (argv.indexFile) {
|
||||
(options = options || {}).indexFile = argv['indexFile'];
|
||||
}
|
||||
|
||||
file = new(statik.Server)(dir, options);
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
var callback = function(e, rsp) {
|
||||
if (e && e.status === 404) {
|
||||
response.writeHead(e.status, e.headers);
|
||||
response.end("Not Found");
|
||||
log(request, response);
|
||||
} else {
|
||||
log(request, response);
|
||||
}
|
||||
};
|
||||
|
||||
if (argv['spa'] && request.url.indexOf(".") == -1) {
|
||||
file.serveFile(argv['indexFile'], 500, {}, request, response);
|
||||
} else {
|
||||
file.serve(request, response, callback);
|
||||
}
|
||||
}).resume();
|
||||
}).listen(+argv.port, argv['host-address']);
|
||||
|
||||
console.log('serving "' + dir + '" at http://' + argv['host-address'] + ':' + argv.port);
|
||||
if (argv.spa) {
|
||||
console.log('serving as a single page app (all non-file requests redirect to ' + argv['indexFile'] +')');
|
||||
}
|
20
Kha/Tools/khamake/node_modules/node-static/examples/file-server.js
generated
vendored
Normal file
20
Kha/Tools/khamake/node_modules/node-static/examples/file-server.js
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
var static = require('../lib/node-static');
|
||||
|
||||
//
|
||||
// Create a node-static server to serve the current directory
|
||||
//
|
||||
var file = new static.Server('.', { cache: 7200, headers: {'X-Hello':'World!'} });
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
file.serve(request, response, function (err, res) {
|
||||
if (err) { // An error as occured
|
||||
console.error("> Error serving " + request.url + " - " + err.message);
|
||||
response.writeHead(err.status, err.headers);
|
||||
response.end();
|
||||
} else { // The file was served successfully
|
||||
console.log("> " + request.url + " - " + res.message);
|
||||
}
|
||||
});
|
||||
}).listen(8080);
|
||||
|
||||
console.log("> node-static is listening on http://127.0.0.1:8080");
|
393
Kha/Tools/khamake/node_modules/node-static/lib/node-static.js
generated
vendored
Normal file
393
Kha/Tools/khamake/node_modules/node-static/lib/node-static.js
generated
vendored
Normal file
@ -0,0 +1,393 @@
|
||||
var fs = require('fs')
|
||||
, events = require('events')
|
||||
, buffer = require('buffer')
|
||||
, http = require('http')
|
||||
, url = require('url')
|
||||
, path = require('path')
|
||||
, mime = require('mime')
|
||||
, util = require('./node-static/util');
|
||||
|
||||
// Current version
|
||||
var version = [0, 7, 9];
|
||||
|
||||
var Server = function (root, options) {
|
||||
if (root && (typeof(root) === 'object')) { options = root; root = null }
|
||||
|
||||
// resolve() doesn't normalize (to lowercase) drive letters on Windows
|
||||
this.root = path.normalize(path.resolve(root || '.'));
|
||||
this.options = options || {};
|
||||
this.cache = 3600;
|
||||
|
||||
this.defaultHeaders = {};
|
||||
this.options.headers = this.options.headers || {};
|
||||
|
||||
this.options.indexFile = this.options.indexFile || "index.html";
|
||||
|
||||
if ('cache' in this.options) {
|
||||
if (typeof(this.options.cache) === 'number') {
|
||||
this.cache = this.options.cache;
|
||||
} else if (! this.options.cache) {
|
||||
this.cache = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ('serverInfo' in this.options) {
|
||||
this.serverInfo = this.options.serverInfo.toString();
|
||||
} else {
|
||||
this.serverInfo = 'node-static/' + version.join('.');
|
||||
}
|
||||
|
||||
this.defaultHeaders['server'] = this.serverInfo;
|
||||
|
||||
if (this.cache !== false) {
|
||||
this.defaultHeaders['cache-control'] = 'max-age=' + this.cache;
|
||||
}
|
||||
|
||||
for (var k in this.defaultHeaders) {
|
||||
this.options.headers[k] = this.options.headers[k] ||
|
||||
this.defaultHeaders[k];
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.serveDir = function (pathname, req, res, finish) {
|
||||
var htmlIndex = path.join(pathname, this.options.indexFile),
|
||||
that = this;
|
||||
|
||||
fs.stat(htmlIndex, function (e, stat) {
|
||||
if (!e) {
|
||||
var status = 200;
|
||||
var headers = {};
|
||||
var originalPathname = decodeURI(url.parse(req.url).pathname);
|
||||
if (originalPathname.length && originalPathname.charAt(originalPathname.length - 1) !== '/') {
|
||||
return finish(301, { 'Location': originalPathname + '/' });
|
||||
} else {
|
||||
that.respond(null, status, headers, [htmlIndex], stat, req, res, finish);
|
||||
}
|
||||
} else {
|
||||
// Stream a directory of files as a single file.
|
||||
fs.readFile(path.join(pathname, 'index.json'), function (e, contents) {
|
||||
if (e) { return finish(404, {}) }
|
||||
var index = JSON.parse(contents);
|
||||
streamFiles(index.files);
|
||||
});
|
||||
}
|
||||
});
|
||||
function streamFiles(files) {
|
||||
util.mstat(pathname, files, function (e, stat) {
|
||||
if (e) { return finish(404, {}) }
|
||||
that.respond(pathname, 200, {}, files, stat, req, res, finish);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.serveFile = function (pathname, status, headers, req, res) {
|
||||
var that = this;
|
||||
var promise = new(events.EventEmitter);
|
||||
|
||||
pathname = this.resolve(pathname);
|
||||
|
||||
fs.stat(pathname, function (e, stat) {
|
||||
if (e) {
|
||||
return promise.emit('error', e);
|
||||
}
|
||||
that.respond(null, status, headers, [pathname], stat, req, res, function (status, headers) {
|
||||
that.finish(status, headers, req, res, promise);
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
};
|
||||
|
||||
Server.prototype.finish = function (status, headers, req, res, promise, callback) {
|
||||
var result = {
|
||||
status: status,
|
||||
headers: headers,
|
||||
message: http.STATUS_CODES[status]
|
||||
};
|
||||
|
||||
headers['server'] = this.serverInfo;
|
||||
|
||||
if (!status || status >= 400) {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
} else {
|
||||
if (promise.listeners('error').length > 0) {
|
||||
promise.emit('error', result);
|
||||
}
|
||||
else {
|
||||
res.writeHead(status, headers);
|
||||
res.end();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Don't end the request here, if we're streaming;
|
||||
// it's taken care of in `prototype.stream`.
|
||||
if (status !== 200 || req.method !== 'GET') {
|
||||
res.writeHead(status, headers);
|
||||
res.end();
|
||||
}
|
||||
callback && callback(null, result);
|
||||
promise.emit('success', result);
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.servePath = function (pathname, status, headers, req, res, finish) {
|
||||
var that = this,
|
||||
promise = new(events.EventEmitter);
|
||||
|
||||
pathname = this.resolve(pathname);
|
||||
|
||||
// Make sure we're not trying to access a
|
||||
// file outside of the root.
|
||||
if (pathname.indexOf(that.root) === 0) {
|
||||
fs.stat(pathname, function (e, stat) {
|
||||
if (e) {
|
||||
finish(404, {});
|
||||
} else if (stat.isFile()) { // Stream a single file.
|
||||
that.respond(null, status, headers, [pathname], stat, req, res, finish);
|
||||
} else if (stat.isDirectory()) { // Stream a directory of files.
|
||||
that.serveDir(pathname, req, res, finish);
|
||||
} else {
|
||||
finish(400, {});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Forbidden
|
||||
finish(403, {});
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
|
||||
Server.prototype.resolve = function (pathname) {
|
||||
return path.resolve(path.join(this.root, pathname));
|
||||
};
|
||||
|
||||
Server.prototype.serve = function (req, res, callback) {
|
||||
var that = this,
|
||||
promise = new(events.EventEmitter),
|
||||
pathname;
|
||||
|
||||
var finish = function (status, headers) {
|
||||
that.finish(status, headers, req, res, promise, callback);
|
||||
};
|
||||
|
||||
try {
|
||||
pathname = decodeURI(url.parse(req.url).pathname);
|
||||
}
|
||||
catch(e) {
|
||||
return process.nextTick(function() {
|
||||
return finish(400, {});
|
||||
});
|
||||
}
|
||||
|
||||
process.nextTick(function () {
|
||||
that.servePath(pathname, 200, {}, req, res, finish).on('success', function (result) {
|
||||
promise.emit('success', result);
|
||||
}).on('error', function (err) {
|
||||
promise.emit('error');
|
||||
});
|
||||
});
|
||||
if (! callback) { return promise }
|
||||
};
|
||||
|
||||
/* Check if we should consider sending a gzip version of the file based on the
|
||||
* file content type and client's Accept-Encoding header value.
|
||||
*/
|
||||
Server.prototype.gzipOk = function (req, contentType) {
|
||||
var enable = this.options.gzip;
|
||||
if(enable &&
|
||||
(typeof enable === 'boolean' ||
|
||||
(contentType && (enable instanceof RegExp) && enable.test(contentType)))) {
|
||||
var acceptEncoding = req.headers['accept-encoding'];
|
||||
return acceptEncoding && acceptEncoding.indexOf("gzip") >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Send a gzipped version of the file if the options and the client indicate gzip is enabled and
|
||||
* we find a .gz file mathing the static resource requested.
|
||||
*/
|
||||
Server.prototype.respondGzip = function (pathname, status, contentType, _headers, files, stat, req, res, finish) {
|
||||
var that = this;
|
||||
if (files.length == 1 && this.gzipOk(req, contentType)) {
|
||||
var gzFile = files[0] + ".gz";
|
||||
fs.stat(gzFile, function (e, gzStat) {
|
||||
if (!e && gzStat.isFile()) {
|
||||
var vary = _headers['Vary'];
|
||||
_headers['Vary'] = (vary && vary != 'Accept-Encoding' ? vary + ', ' : '') + 'Accept-Encoding';
|
||||
_headers['Content-Encoding'] = 'gzip';
|
||||
stat.size = gzStat.size;
|
||||
files = [gzFile];
|
||||
}
|
||||
that.respondNoGzip(pathname, status, contentType, _headers, files, stat, req, res, finish);
|
||||
});
|
||||
} else {
|
||||
// Client doesn't want gzip or we're sending multiple files
|
||||
that.respondNoGzip(pathname, status, contentType, _headers, files, stat, req, res, finish);
|
||||
}
|
||||
}
|
||||
|
||||
Server.prototype.parseByteRange = function (req, stat) {
|
||||
var byteRange = {
|
||||
from: 0,
|
||||
to: 0,
|
||||
valid: false
|
||||
}
|
||||
|
||||
var rangeHeader = req.headers['range'];
|
||||
var flavor = 'bytes=';
|
||||
|
||||
if (rangeHeader) {
|
||||
if (rangeHeader.indexOf(flavor) == 0 && rangeHeader.indexOf(',') == -1) {
|
||||
/* Parse */
|
||||
rangeHeader = rangeHeader.substr(flavor.length).split('-');
|
||||
byteRange.from = parseInt(rangeHeader[0]);
|
||||
byteRange.to = parseInt(rangeHeader[1]);
|
||||
|
||||
/* Replace empty fields of differential requests by absolute values */
|
||||
if (isNaN(byteRange.from) && !isNaN(byteRange.to)) {
|
||||
byteRange.from = stat.size - byteRange.to;
|
||||
byteRange.to = stat.size ? stat.size - 1 : 0;
|
||||
} else if (!isNaN(byteRange.from) && isNaN(byteRange.to)) {
|
||||
byteRange.to = stat.size ? stat.size - 1 : 0;
|
||||
}
|
||||
|
||||
/* General byte range validation */
|
||||
if (!isNaN(byteRange.from) && !!byteRange.to && 0 <= byteRange.from && byteRange.from < byteRange.to) {
|
||||
byteRange.valid = true;
|
||||
} else {
|
||||
console.warn("Request contains invalid range header: ", rangeHeader);
|
||||
}
|
||||
} else {
|
||||
console.warn("Request contains unsupported range header: ", rangeHeader);
|
||||
}
|
||||
}
|
||||
return byteRange;
|
||||
}
|
||||
|
||||
Server.prototype.respondNoGzip = function (pathname, status, contentType, _headers, files, stat, req, res, finish) {
|
||||
var mtime = Date.parse(stat.mtime),
|
||||
key = pathname || files[0],
|
||||
headers = {},
|
||||
clientETag = req.headers['if-none-match'],
|
||||
clientMTime = Date.parse(req.headers['if-modified-since']),
|
||||
startByte = 0,
|
||||
length = stat.size,
|
||||
byteRange = this.parseByteRange(req, stat);
|
||||
|
||||
/* Handle byte ranges */
|
||||
if (files.length == 1 && byteRange.valid) {
|
||||
if (byteRange.to < length) {
|
||||
|
||||
// Note: HTTP Range param is inclusive
|
||||
startByte = byteRange.from;
|
||||
length = byteRange.to - byteRange.from + 1;
|
||||
status = 206;
|
||||
|
||||
// Set Content-Range response header (we advertise initial resource size on server here (stat.size))
|
||||
headers['Content-Range'] = 'bytes ' + byteRange.from + '-' + byteRange.to + '/' + stat.size;
|
||||
|
||||
} else {
|
||||
byteRange.valid = false;
|
||||
console.warn("Range request exceeds file boundaries, goes until byte no", byteRange.to, "against file size of", length, "bytes");
|
||||
}
|
||||
}
|
||||
|
||||
/* In any case, check for unhandled byte range headers */
|
||||
if (!byteRange.valid && req.headers['range']) {
|
||||
console.error(new Error("Range request present but invalid, might serve whole file instead"));
|
||||
}
|
||||
|
||||
// Copy default headers
|
||||
for (var k in this.options.headers) { headers[k] = this.options.headers[k] }
|
||||
// Copy custom headers
|
||||
for (var k in _headers) { headers[k] = _headers[k] }
|
||||
|
||||
headers['Etag'] = JSON.stringify([stat.ino, stat.size, mtime].join('-'));
|
||||
headers['Date'] = new(Date)().toUTCString();
|
||||
headers['Last-Modified'] = new(Date)(stat.mtime).toUTCString();
|
||||
headers['Content-Type'] = contentType;
|
||||
headers['Content-Length'] = length;
|
||||
|
||||
for (var k in _headers) { headers[k] = _headers[k] }
|
||||
|
||||
// Conditional GET
|
||||
// If the "If-Modified-Since" or "If-None-Match" headers
|
||||
// match the conditions, send a 304 Not Modified.
|
||||
if ((clientMTime || clientETag) &&
|
||||
(!clientETag || clientETag === headers['Etag']) &&
|
||||
(!clientMTime || clientMTime >= mtime)) {
|
||||
// 304 response should not contain entity headers
|
||||
['Content-Encoding',
|
||||
'Content-Language',
|
||||
'Content-Length',
|
||||
'Content-Location',
|
||||
'Content-MD5',
|
||||
'Content-Range',
|
||||
'Content-Type',
|
||||
'Expires',
|
||||
'Last-Modified'].forEach(function (entityHeader) {
|
||||
delete headers[entityHeader];
|
||||
});
|
||||
finish(304, headers);
|
||||
} else {
|
||||
res.writeHead(status, headers);
|
||||
|
||||
this.stream(key, files, length, startByte, res, function (e) {
|
||||
if (e) { return finish(500, {}) }
|
||||
finish(status, headers);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Server.prototype.respond = function (pathname, status, _headers, files, stat, req, res, finish) {
|
||||
var contentType = _headers['Content-Type'] ||
|
||||
mime.lookup(files[0]) ||
|
||||
'application/octet-stream';
|
||||
|
||||
if(this.options.gzip) {
|
||||
this.respondGzip(pathname, status, contentType, _headers, files, stat, req, res, finish);
|
||||
} else {
|
||||
this.respondNoGzip(pathname, status, contentType, _headers, files, stat, req, res, finish);
|
||||
}
|
||||
}
|
||||
|
||||
Server.prototype.stream = function (pathname, files, length, startByte, res, callback) {
|
||||
|
||||
(function streamFile(files, offset) {
|
||||
var file = files.shift();
|
||||
|
||||
if (file) {
|
||||
file = path.resolve(file) === path.normalize(file) ? file : path.join(pathname || '.', file);
|
||||
|
||||
// Stream the file to the client
|
||||
fs.createReadStream(file, {
|
||||
flags: 'r',
|
||||
mode: 0666,
|
||||
start: startByte,
|
||||
end: startByte + (length ? length - 1 : 0)
|
||||
}).on('data', function (chunk) {
|
||||
// Bounds check the incoming chunk and offset, as copying
|
||||
// a buffer from an invalid offset will throw an error and crash
|
||||
if (chunk.length && offset < length && offset >= 0) {
|
||||
offset += chunk.length;
|
||||
}
|
||||
}).on('close', function () {
|
||||
streamFile(files, offset);
|
||||
}).on('error', function (err) {
|
||||
callback(err);
|
||||
console.error(err);
|
||||
}).pipe(res, { end: false });
|
||||
} else {
|
||||
res.end();
|
||||
callback(null, offset);
|
||||
}
|
||||
})(files.slice(0), 0);
|
||||
};
|
||||
|
||||
// Exports
|
||||
exports.Server = Server;
|
||||
exports.version = version;
|
||||
exports.mime = mime;
|
||||
|
||||
|
||||
|
30
Kha/Tools/khamake/node_modules/node-static/lib/node-static/util.js
generated
vendored
Normal file
30
Kha/Tools/khamake/node_modules/node-static/lib/node-static/util.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
var fs = require('fs')
|
||||
, path = require('path');
|
||||
|
||||
exports.mstat = function (dir, files, callback) {
|
||||
(function mstat(files, stats) {
|
||||
var file = files.shift();
|
||||
|
||||
if (file) {
|
||||
fs.stat(path.join(dir, file), function (e, stat) {
|
||||
if (e) {
|
||||
callback(e);
|
||||
} else {
|
||||
mstat(files, stats.concat([stat]));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback(null, {
|
||||
size: stats.reduce(function (total, stat) {
|
||||
return total + stat.size;
|
||||
}, 0),
|
||||
mtime: stats.reduce(function (latest, stat) {
|
||||
return latest > stat.mtime ? latest : stat.mtime;
|
||||
}, 0),
|
||||
ino: stats.reduce(function (total, stat) {
|
||||
return total + stat.ino;
|
||||
}, 0)
|
||||
});
|
||||
}
|
||||
})(files.slice(0), []);
|
||||
};
|
49
Kha/Tools/khamake/node_modules/node-static/package.json
generated
vendored
Normal file
49
Kha/Tools/khamake/node_modules/node-static/package.json
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "node-static",
|
||||
"description": "simple, compliant file streaming module for node",
|
||||
"url": "http://github.com/cloudhead/node-static",
|
||||
"keywords": [
|
||||
"http",
|
||||
"static",
|
||||
"file",
|
||||
"server"
|
||||
],
|
||||
"author": "Alexis Sellier <alexis@cloudhead.io>",
|
||||
"contributors": [
|
||||
"Pablo Cantero <pablo@pablocantero.com>",
|
||||
"Ionică Bizău <bizauionica@gmail.com>"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/cloudhead/node-static"
|
||||
},
|
||||
"main": "./lib/node-static",
|
||||
"scripts": {
|
||||
"test": "vows --spec --isolate"
|
||||
},
|
||||
"bin": {
|
||||
"static": "bin/cli.js"
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"optimist": ">=0.3.4",
|
||||
"colors": ">=0.6.0",
|
||||
"mime": "^1.2.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"request": "latest",
|
||||
"vows": "latest"
|
||||
},
|
||||
"version": "0.7.10",
|
||||
"engines": {
|
||||
"node": ">= 0.4.1"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/cloudhead/node-static/issues"
|
||||
},
|
||||
"homepage": "https://github.com/cloudhead/node-static",
|
||||
"directories": {
|
||||
"example": "examples",
|
||||
"test": "test"
|
||||
}
|
||||
}
|
0
Kha/Tools/khamake/node_modules/node-static/test/fixtures/empty.css
generated
vendored
Normal file
0
Kha/Tools/khamake/node_modules/node-static/test/fixtures/empty.css
generated
vendored
Normal file
1
Kha/Tools/khamake/node_modules/node-static/test/fixtures/hello.txt
generated
vendored
Normal file
1
Kha/Tools/khamake/node_modules/node-static/test/fixtures/hello.txt
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
hello world
|
8
Kha/Tools/khamake/node_modules/node-static/test/fixtures/index.html
generated
vendored
Normal file
8
Kha/Tools/khamake/node_modules/node-static/test/fixtures/index.html
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Awesome page</title>
|
||||
</head>
|
||||
<body>
|
||||
hello world!
|
||||
</body>
|
||||
</html>
|
8
Kha/Tools/khamake/node_modules/node-static/test/fixtures/there/index.html
generated
vendored
Normal file
8
Kha/Tools/khamake/node_modules/node-static/test/fixtures/there/index.html
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Other page</title>
|
||||
</head>
|
||||
<body>
|
||||
hello there!
|
||||
</body>
|
||||
</html>
|
390
Kha/Tools/khamake/node_modules/node-static/test/integration/node-static-test.js
generated
vendored
Normal file
390
Kha/Tools/khamake/node_modules/node-static/test/integration/node-static-test.js
generated
vendored
Normal file
@ -0,0 +1,390 @@
|
||||
var vows = require('vows')
|
||||
, request = require('request')
|
||||
, assert = require('assert')
|
||||
, static = require('../../lib/node-static');
|
||||
|
||||
var fileServer = new static.Server(__dirname + '/../fixtures');
|
||||
var suite = vows.describe('node-static');
|
||||
var TEST_PORT = 8080;
|
||||
var TEST_SERVER = 'http://localhost:' + TEST_PORT;
|
||||
var version = static.version.join('.');
|
||||
var server;
|
||||
var callback;
|
||||
|
||||
headers = {
|
||||
'requesting headers': {
|
||||
topic : function(){
|
||||
request.head(TEST_SERVER + '/index.html', this.callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
headers['requesting headers']['should respond with node-static/' + version] = function(error, response, body){
|
||||
assert.equal(response.headers['server'], 'node-static/' + version);
|
||||
}
|
||||
|
||||
suite.addBatch({
|
||||
'once an http server is listening with a callback': {
|
||||
topic: function () {
|
||||
server = require('http').createServer(function (request, response) {
|
||||
fileServer.serve(request, response, function(err, result) {
|
||||
if (callback)
|
||||
callback(request, response, err, result);
|
||||
else
|
||||
request.end();
|
||||
});
|
||||
}).listen(TEST_PORT, this.callback)
|
||||
},
|
||||
'should be listening' : function(){
|
||||
/* This test is necessary to ensure the topic execution.
|
||||
* A topic without tests will be not executed */
|
||||
assert.isTrue(true);
|
||||
}
|
||||
},
|
||||
}).addBatch({
|
||||
'streaming a 404 page': {
|
||||
topic: function(){
|
||||
callback = function(request, response, err, result) {
|
||||
if (err) {
|
||||
response.writeHead(err.status, err.headers);
|
||||
setTimeout(function() {
|
||||
response.end('Custom 404 Stream.')
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
request.get(TEST_SERVER + '/not-found', this.callback);
|
||||
},
|
||||
'should respond with 404' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 404);
|
||||
},
|
||||
'should respond with the streamed content': function(error, response, body){
|
||||
callback = null;
|
||||
assert.equal(body, 'Custom 404 Stream.');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'once an http server is listening without a callback': {
|
||||
topic: function () {
|
||||
server.close();
|
||||
server = require('http').createServer(function (request, response) {
|
||||
fileServer.serve(request, response);
|
||||
}).listen(TEST_PORT, this.callback)
|
||||
},
|
||||
'should be listening' : function(){
|
||||
/* This test is necessary to ensure the topic execution.
|
||||
* A topic without tests will be not executed */
|
||||
assert.isTrue(true);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'requesting a file not found': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/not-found', this.callback);
|
||||
},
|
||||
'should respond with 404' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 404);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'requesting a malformed URI': {
|
||||
topic: function(){
|
||||
request.get(TEST_SERVER + '/a%AFc', this.callback);
|
||||
},
|
||||
'should respond with 400': function(error, response, body){
|
||||
assert.equal(response.statusCode, 400);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'serving empty.css': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/empty.css', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with text/css': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/css');
|
||||
},
|
||||
'should respond with empty string': function(error, response, body){
|
||||
assert.equal(body, '');
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'serving hello.txt': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/hello.txt', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with text/plain': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/plain');
|
||||
},
|
||||
'should respond with hello world': function(error, response, body){
|
||||
assert.equal(body, 'hello world');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving first 5 bytes of hello.txt': {
|
||||
topic : function(){
|
||||
var options = {
|
||||
url: TEST_SERVER + '/hello.txt',
|
||||
headers: {
|
||||
'Range': 'bytes=0-4'
|
||||
}
|
||||
};
|
||||
request.get(options, this.callback);
|
||||
},
|
||||
'should respond with 206' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 206);
|
||||
},
|
||||
'should respond with text/plain': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/plain');
|
||||
},
|
||||
'should have content-length of 5 bytes': function(error, response, body){
|
||||
assert.equal(response.headers['content-length'], 5);
|
||||
},
|
||||
'should have a valid Content-Range header in response': function(error, response, body){
|
||||
assert.equal(response.headers['content-range'], 'bytes 0-4/11');
|
||||
},
|
||||
'should respond with hello': function(error, response, body){
|
||||
assert.equal(body, 'hello');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving last 5 bytes of hello.txt': {
|
||||
topic : function(){
|
||||
var options = {
|
||||
url: TEST_SERVER + '/hello.txt',
|
||||
headers: {
|
||||
'Range': 'bytes=6-10'
|
||||
}
|
||||
};
|
||||
request.get(options, this.callback);
|
||||
},
|
||||
'should respond with 206' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 206);
|
||||
},
|
||||
'should respond with text/plain': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/plain');
|
||||
},
|
||||
'should have content-length of 5 bytes': function(error, response, body){
|
||||
assert.equal(response.headers['content-length'], 5);
|
||||
},
|
||||
'should have a valid Content-Range header in response': function(error, response, body){
|
||||
assert.equal(response.headers['content-range'], 'bytes 6-10/11');
|
||||
},
|
||||
'should respond with world': function(error, response, body){
|
||||
assert.equal(body, 'world');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving all from the start of hello.txt': {
|
||||
topic : function(){
|
||||
var options = {
|
||||
url: TEST_SERVER + '/hello.txt',
|
||||
headers: {
|
||||
'Range': 'bytes=0-'
|
||||
}
|
||||
};
|
||||
request.get(options, this.callback);
|
||||
},
|
||||
'should respond with 206' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 206);
|
||||
},
|
||||
'should respond with text/plain': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/plain');
|
||||
},
|
||||
'should have content-length of 11 bytes': function(error, response, body){
|
||||
assert.equal(response.headers['content-length'], 11);
|
||||
},
|
||||
'should have a valid Content-Range header in response': function(error, response, body){
|
||||
assert.equal(response.headers['content-range'], 'bytes 0-10/11');
|
||||
},
|
||||
'should respond with "hello world"': function(error, response, body){
|
||||
assert.equal(body, 'hello world');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving directory index': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER, this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with text/html': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/html');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving index.html from the cache': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/index.html', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with text/html': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/html');
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'requesting with If-None-Match': {
|
||||
topic : function(){
|
||||
var _this = this;
|
||||
request.get(TEST_SERVER + '/index.html', function(error, response, body){
|
||||
request({
|
||||
method: 'GET',
|
||||
uri: TEST_SERVER + '/index.html',
|
||||
headers: {'if-none-match': response.headers['etag']}
|
||||
},
|
||||
_this.callback);
|
||||
});
|
||||
},
|
||||
'should respond with 304' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 304);
|
||||
}
|
||||
},
|
||||
'requesting with If-None-Match and If-Modified-Since': {
|
||||
topic : function(){
|
||||
var _this = this;
|
||||
request.get(TEST_SERVER + '/index.html', function(error, response, body){
|
||||
var modified = Date.parse(response.headers['last-modified']);
|
||||
var oneDayLater = new Date(modified + (24 * 60 * 60 * 1000)).toUTCString();
|
||||
var nonMatchingEtag = '1111222233334444';
|
||||
request({
|
||||
method: 'GET',
|
||||
uri: TEST_SERVER + '/index.html',
|
||||
headers: {
|
||||
'if-none-match': nonMatchingEtag,
|
||||
'if-modified-since': oneDayLater
|
||||
}
|
||||
},
|
||||
_this.callback);
|
||||
});
|
||||
},
|
||||
'should respond with a 200': function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'requesting POST': {
|
||||
topic : function(){
|
||||
request.post(TEST_SERVER + '/index.html', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should not be empty' : function(error, response, body){
|
||||
assert.isNotEmpty(body);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'requesting HEAD': {
|
||||
topic : function(){
|
||||
request.head(TEST_SERVER + '/index.html', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'head must has no body' : function(error, response, body){
|
||||
assert.isEmpty(body);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch(headers)
|
||||
.addBatch({
|
||||
'addings custom mime types': {
|
||||
topic : function(){
|
||||
static.mime.define({'application/font-woff': ['woff']});
|
||||
this.callback();
|
||||
},
|
||||
'should add woff' : function(error, response, body){
|
||||
assert.equal(static.mime.lookup('woff'), 'application/font-woff');
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'serving subdirectory index': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/there/', this.callback); // with trailing slash
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with text/html': function(error, response, body){
|
||||
assert.equal(response.headers['content-type'], 'text/html');
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'redirecting to subdirectory index': {
|
||||
topic : function(){
|
||||
request.get({ url: TEST_SERVER + '/there', followRedirect: false }, this.callback); // without trailing slash
|
||||
},
|
||||
'should respond with 301' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 301);
|
||||
},
|
||||
'should respond with location header': function(error, response, body){
|
||||
assert.equal(response.headers['location'], '/there/'); // now with trailing slash
|
||||
},
|
||||
'should respond with empty string body' : function(error, response, body){
|
||||
assert.equal(body, '');
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'requesting a subdirectory (with trailing slash) not found': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/notthere/', this.callback); // with trailing slash
|
||||
},
|
||||
'should respond with 404' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 404);
|
||||
}
|
||||
}
|
||||
})
|
||||
.addBatch({
|
||||
'requesting a subdirectory (without trailing slash) not found': {
|
||||
topic : function(){
|
||||
request.get({ url: TEST_SERVER + '/notthere', followRedirect: false }, this.callback); // without trailing slash
|
||||
},
|
||||
'should respond with 404' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 404);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'once an http server is listening with custom index configuration': {
|
||||
topic: function () {
|
||||
server.close();
|
||||
|
||||
fileServer = new static.Server(__dirname + '/../fixtures', { indexFile: "hello.txt" });
|
||||
|
||||
server = require('http').createServer(function (request, response) {
|
||||
fileServer.serve(request, response);
|
||||
}).listen(TEST_PORT, this.callback)
|
||||
},
|
||||
'should be listening' : function(){
|
||||
/* This test is necessary to ensure the topic execution.
|
||||
* A topic without tests will be not executed */
|
||||
assert.isTrue(true);
|
||||
}
|
||||
}
|
||||
}).addBatch({
|
||||
'serving custom index file': {
|
||||
topic : function(){
|
||||
request.get(TEST_SERVER + '/', this.callback);
|
||||
},
|
||||
'should respond with 200' : function(error, response, body){
|
||||
assert.equal(response.statusCode, 200);
|
||||
},
|
||||
'should respond with empty string': function(error, response, body){
|
||||
assert.equal(body, 'hello world');
|
||||
}
|
||||
}
|
||||
}).export(module);
|
||||
|
Reference in New Issue
Block a user