Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial Commit

  • Loading branch information...
commit c893a1d506c2222513e9cdf08dbc2a4f17f815c5 0 parents
@creationix authored
118 node_modules/continuable.js
@@ -0,0 +1,118 @@
+var nativeFs = process.binding('fs')
+
+var fs = exports.fs = (function () {
+
+ var constants = require('constants');
+
+ function stringToFlags(string) {
+ if (typeof string === "number") return string;
+ switch (string) {
+ case 'r': return constants.O_RDONLY;
+ case 'r+': return constants.O_RDWR;
+ case 'w': return constants.O_CREAT | constants.O_TRUNC | constants.O_WRONLY;
+ case 'w+': return constants.O_CREAT | constants.O_TRUNC | constants.O_RDWR;
+ case 'a': return constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY;
+ case 'a+': return constants.O_APPEND | constants.O_CREAT | constants.O_RDWR;
+ default: throw new Error("Unknown flag string " + JSON.stringify(string));
+ }
+ }
+
+ function noop(err) {
+ if (err) console.error(err.stack);
+ }
+
+ function ReadStream(fd) {
+ this.fd = fd;
+ this.buffer = new Buffer(this.chunkSize);
+ this.position = 0;
+ }
+ ReadStream.prototype.chunkSize = 1024 * 40;
+ ReadStream.prototype.read = function () {
+ var self = this;
+ return function (callback) {
+ read(self.fd, self.buffer, 0, self.chunkSize, self.position)(function (err, bytesRead) {
+ if (err) return callback(err);
+ self.position += bytesRead;
+ if (bytesRead) {
+ return callback(null, self.buffer.slice(0, bytesRead));
+ }
+ callback();
+ });
+ }
+ }
+ ReadStream.prototype.close = function () {
+ return close(this.fd);
+ };
+
+ function WriteStream(fd) {
+ this.fd = fd;
+ this.position = 0;
+ }
+ WriteStream.prototype.write = function (chunk) {
+ var self = this;
+ return function (callback) {
+ if (!chunk) { return callback(); }
+ write(self.fd, chunk, 0, chunk.length, self.position)(function (err, bytesWritten) {
+ if (err) return callback(err);
+ self.position += bytesWritten;
+ callback(null, bytesWritten);
+ });
+ };
+ };
+ WriteStream.prototype.close = ReadStream.prototype.close;
+
+ function open(path, flags, mode) {
+ return function (callback) {
+ return nativeFs.open(path, stringToFlags(flags), mode || 0666, callback || noop);
+ };
+ }
+
+ function read(fd, buffer, offset, length, position) {
+ return function (callback) {
+ return nativeFs.read(fd, buffer, offset, length, position, callback || noop)
+ };
+ };
+
+ function write(fd, buffer, offset, length, position) {
+ return function (callback) {
+ return nativeFs.write(fd, buffer, offset, length, position, callback || noop);
+ };
+ };
+
+ function close(fd) {
+ return function (callback) {
+ return nativeFs.close(fd, callback || noop);
+ };
+ };
+
+ function stat(path) {
+ return function (callback) {
+ return nativeFs.stat(path, callback || noop);
+ };
+ };
+
+ function fstat(fd) {
+ return function (callback) {
+ return nativeFs.fstat(fd, callback || noop);
+ };
+ };
+
+ function lstat(path) {
+ return function (callback) {
+ return nativeFs.lstat(path, callback || noop);
+ };
+ };
+
+ return {
+ ReadStream: ReadStream,
+ WriteStream: WriteStream,
+ open: open,
+ read: read,
+ write: write,
+ close: close,
+ stat: stat,
+ fstat: fstat,
+ lstat: lstat
+ };
+
+})();
89 node_modules/middle.js
@@ -0,0 +1,89 @@
+var Stream = require('stream').Stream;
+var urlParse = require('url').parse;
+
+exports.log = function (app) {
+ return function (req, res) {
+ var method = req.method;
+ var url = req.url;
+ app(req, function (code, headers, body) {
+ console.log(method + " " + url + " " + code);
+ res(code, headers, body);
+ });
+ };
+};
+
+// Moves the raw headers to .rawHeaders and makes easy to access headers at .headers
+// Also adds missing headers in response like Date, Server, and Content-Length
+exports.autoHeaders = function (app) {
+ return function (req, res) {
+ // Make the headers more user friendly
+ var rawHeaders = req.rawHeaders = req.headers;
+ var headers = req.headers = {};
+ for (var i = 0, l = rawHeaders.length; i < l; i += 2) {
+ headers[rawHeaders[i].toLowerCase()] = rawHeaders[i + 1];
+ }
+
+ // Parse the url and store the original in rawUrl
+ var rawUrl = req.rawUrl = req.url;
+ req.url = urlParse(rawUrl);
+
+ app(req, function (code, headers, body) {
+ var hasContentLength, hasTransferEncoding, hasDate, hasServer;
+ for (var key in headers) {
+ switch (key.toLowerCase()) {
+ case "date": hasDate = true; continue;
+ case "server": hasServer = true; continue;
+ case "content-length": hasContentLength = true; continue;
+ case "transfer-encoding": hasTransferEncoding = true; continue;
+ }
+ }
+ if (!hasDate) {
+ headers["Date"] = (new Date).toUTCString();
+ }
+ if (!hasServer) {
+ headers["Server"] = "node " + process.version;
+ }
+ if (body && !hasContentLength && !hasTransferEncoding) {
+ var isStreaming = body && typeof body === "object" && typeof body.pipe === "function";
+ if (!isStreaming) {
+ body += "";
+ headers["Content-Length"] = Buffer.byteLength(body);
+ hasContentLength = true;
+ }
+ else {
+ headers["Transfer-Encoding"] = "chunked";
+ hasTransferEncoding = true;
+ var originalBody = body;
+ body = new Stream();
+ body.readable = true;
+
+ originalBody.on("data", function (chunk) {
+ if (Buffer.isBuffer(chunk)) {
+ body.emit("data", chunk.length.toString(16).toUpperCase() + "\r\n");
+ body.emit("data", chunk);
+ body.emit("data", "\r\n");
+ return;
+ }
+ var length = Buffer.byteLength(chunk);
+ body.emit("data", toString(16).toUpperCase() + "\r\n" + chunk + "\r\n");
+ });
+
+ originalBody.on("end", function () {
+ body.emit("data", "0\r\n\r\n\r\n");
+ body.emit("end")
+ });
+ }
+ }
+
+ if (req.shouldKeepAlive && (hasContentLength || hasTransferEncoding || code == 304)) {
+ headers["Connection"] = "keep-alive"
+ }
+ else {
+ headers["Connection"] = "close"
+ req.shouldKeepAlive = false
+ }
+
+ res(code, headers, body);
+ });
+ };
+};
123 node_modules/web.js
@@ -0,0 +1,123 @@
+var HTTPParser = process.binding("http_parser").HTTPParser;
+var Stream = require('stream').Stream;
+
+var STATUS_CODES = {
+ '100': 'Continue',
+ '101': 'Switching Protocols',
+ '102': 'Processing', // RFC 2518, obsoleted by RFC 4918
+ '200': 'OK',
+ '201': 'Created',
+ '202': 'Accepted',
+ '203': 'Non-Authoritative Information',
+ '204': 'No Content',
+ '205': 'Reset Content',
+ '206': 'Partial Content',
+ '207': 'Multi-Status', // RFC 4918
+ '300': 'Multiple Choices',
+ '301': 'Moved Permanently',
+ '302': 'Moved Temporarily',
+ '303': 'See Other',
+ '304': 'Not Modified',
+ '305': 'Use Proxy',
+ '307': 'Temporary Redirect',
+ '400': 'Bad Request',
+ '401': 'Unauthorized',
+ '402': 'Payment Required',
+ '403': 'Forbidden',
+ '404': 'Not Found',
+ '405': 'Method Not Allowed',
+ '406': 'Not Acceptable',
+ '407': 'Proxy Authentication Required',
+ '408': 'Request Time-out',
+ '409': 'Conflict',
+ '410': 'Gone',
+ '411': 'Length Required',
+ '412': 'Precondition Failed',
+ '413': 'Request Entity Too Large',
+ '414': 'Request-URI Too Large',
+ '415': 'Unsupported Media Type',
+ '416': 'Requested Range Not Satisfiable',
+ '417': 'Expectation Failed',
+ '418': 'I\'m a teapot', // RFC 2324
+ '422': 'Unprocessable Entity', // RFC 4918
+ '423': 'Locked', // RFC 4918
+ '424': 'Failed Dependency', // RFC 4918
+ '425': 'Unordered Collection', // RFC 4918
+ '426': 'Upgrade Required', // RFC 2817
+ '500': 'Internal Server Error',
+ '501': 'Not Implemented',
+ '502': 'Bad Gateway',
+ '503': 'Service Unavailable',
+ '504': 'Gateway Time-out',
+ '505': 'HTTP Version not supported',
+ '506': 'Variant Also Negotiates', // RFC 2295
+ '507': 'Insufficient Storage', // RFC 4918
+ '509': 'Bandwidth Limit Exceeded',
+ '510': 'Not Extended' // RFC 2774
+};
+
+exports.socketHandler = function (app) {
+ return function (client) {
+ var parser = new HTTPParser(HTTPParser.REQUEST);
+ var req;
+
+ parser.onHeadersComplete = function (info) {
+ info.__proto__ = Stream.prototype;
+ Stream.call(info);
+ req = info;
+ req.readable = true;
+ app(req, function (statusCode, headers, body) {
+ var reasonPhrase = STATUS_CODES[statusCode];
+ if (!reasonPhrase) {
+ throw new Error("Invalid response code " + statusCode);
+ }
+ var head = "HTTP/1.1 " + statusCode + " " + reasonPhrase + "\r\n";
+ for (var key in headers) {
+ head += key + ": " + headers[key] + "\r\n";
+ }
+ head += "\r\n";
+
+ var isStreaming = body && typeof body === "object" && typeof body.pipe === "function";
+
+ if (body && !isStreaming) head += body;
+
+ client.write(head);
+
+ if (!isStreaming) {
+ return done()
+ }
+
+ body.pipe(client);
+ body.on("end", done);
+
+ });
+ }
+
+ parser.onBody = function (buf, start, len) {
+ req.emit("data", buf.slide(start, len));
+ };
+
+ parser.onMessageComplete = function () {
+ req.emit("end");
+ };
+
+ client.on("data", function (chunk) {
+ var ret = parser.execute(chunk, 0, chunk.length);
+ // TODO: handle error cases in ret
+ });
+
+ client.on("end", function () {
+ parser.finish();
+ });
+
+ function done() {
+ console.log(req);
+ if (req.shouldKeepAlive) {
+ parser.reinitialize(HTTPParser.REQUEST);
+ }
+ else {
+ client.end();
+ }
+ }
+ };
+};
52 test-fs.js
@@ -0,0 +1,52 @@
+var fs = require('continuable').fs;
+
+copy(__filename, __filename + ".copy")(onCopy)
+
+function copy(inputPath, outputPath) {
+ console.log("Copying %s to %s", inputPath, outputPath);
+
+ return function (callback) {
+ var input, output;
+ var totalWritten = 0;
+
+ fs.open(inputPath, "r")(onOpenInput);
+
+ function onOpenInput(err, fd) {
+ if (err) return done(err);
+ input = new fs.ReadStream(fd);
+ fs.open(outputPath, "w")(onOpenOutput);
+ }
+
+ function onOpenOutput(err, fd) {
+ if (err) return done(err);
+ output = new fs.WriteStream(fd);
+ input.read()(onRead);
+ }
+
+ function onRead(err, chunk) {
+ if (err) return done(err);
+ output.write(chunk)(onWrite);
+ }
+
+ function onWrite(err, bytesWritten) {
+ if (err) return done(err);
+ if (bytesWritten) {
+ totalWritten += bytesWritten;
+ return input.read()(onRead);
+ }
+ return done();
+ }
+
+ function done(err) {
+ input && input.close()();
+ output && output.close()();
+ callback(err, totalWritten);
+ }
+
+ };
+}
+
+function onCopy(err, bytes) {
+ if (err) throw err;
+ console.log("copied %s bytes", bytes);
+}
44 test-web.js
@@ -0,0 +1,44 @@
+var middle = require('middle');
+var fs = require('fs');
+
+function app(req, res) {
+ var isHead;
+ var method = req.method;
+ if (method === "HEAD") {
+ method = "GET";
+ isHead = true;
+ }
+ if (!method === "GET") return res(404, {}, "");
+
+ // fs.open(__filename, "r", function (err, fd) {
+ // if (err) throw err;
+ // fs.fstat(fd, function (err, stat) {
+ // if (err) throw err;
+ // var input;
+ // if (isHead) {
+ // fs.close(fd);
+ // }
+ // else {
+ // input = fs.createReadStream(null, {fd:fd});
+ // }
+ // res(200, {
+ // "ETag": '"' + stat.ino.toString(36) + "-" + stat.size.toString(36) + "-" + stat.mtime.valueOf().toString(36) + '"',
+ // "Content-Type": "application/javascript",
+ // "Content-Length": stat.size
+ // }, input);
+ // });
+ // });
+ res(200, {
+ "Content-Type": "text/plain",
+ }, "Hello World\n");
+}
+
+app = middle.autoHeaders(app);
+
+app = middle.log(app);
+
+var server = require('net').createServer(require('web').socketHandler(app));
+server.listen(8080, function () {
+ var address = server.address();
+ console.log("http://%s:%s/", address.address, address.port);
+});

0 comments on commit c893a1d

Please sign in to comment.
Something went wrong with that request. Please try again.