var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); }).listen(8888);
var PORT = 8000; var http = require('http'); var server = http.createServer(function(request, response) { // TODO }); server.listen(PORT); console.log("Server runing at port: " + PORT + ".");
var url = require("url"); var pathname = url.parse(request.url).pathname;
var server = http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname; response.write(pathname); response.end(); });
var fs = require("fs");
var path = require("path");
var server = http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname; var realPath = "assets" + pathname; path.exists(realPath, function (exists) { if (!exists) { response.writeHead(404, {'Content-Type': 'text/plain'}); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { fs.readFile(realPath, "binary", function(err, file) { if (err) { response.writeHead(500, {'Content-Type': 'text/plain'}); response.end(err); } else { response.writeHead(200, {'Content-Type': 'text/html'}); response.write(file, "binary"); response.end(); } }); } }); });
exports.types = { "css": "text/css", "gif": "image/gif", "html": "text/html", "ico": "image/x-icon", "jpeg": "image/jpeg", "jpg": "image/jpeg", "js": "text/javascript", "json": "application/json", "pdf": "application/pdf", "png": "image/png", "svg": "image/svg+xml", "swf": "application/x-shockwave-flash", "tiff": "image/tiff", "txt": "text/plain", "wav": "audio/x-wav", "wma": "audio/x-ms-wma", "wmv": "video/x-ms-wmv", "xml": "text/xml" };
var mime = require("./mime").types;
var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown';
var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; var contentType = mime[ext] || "text/plain"; response.writeHead(200, {'Content-Type': contentType}); response.write(file, "binary"); response.end();
Connection: keep-alive Content-Type: text/html Transfer-Encoding: chunked
exports.Expires = { fileMatch: /^(gif|png|jpg|js|css)$/ig, maxAge: 60*60*24*365 };
var config = require("./config");
var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; if (ext.match(config.Expires.fileMatch)) { var expires = new Date(); expires.setTime(expires.getTime() + config.Expires.maxAge * 1000); response.setHeader("Expires", expires.toUTCString()); response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge); }
Cache-Control: max-age=31536000 Connection: keep-alive Content-Type: image/png Expires: Fri, 09 Nov 2012 12:55:41 GMT Transfer-Encoding: chunked
fs.stat(realPath, function (err, stat) { var lastModified = stat.mtime.toUTCString(); response.setHeader("Last-Modified", lastModified); });
if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, "Not Modified"); response.end(); }
var server = http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname;console.log(pathname); var realPath = path.join("assets", pathname); path.exists(realPath, function (exists) { if (!exists) { response.writeHead(404, "Not Found", {'Content-Type': 'text/plain'}); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; var contentType = mime[ext] || "text/plain"; response.setHeader("Content-Type", contentType); fs.stat(realPath, function (err, stat) { var lastModified = stat.mtime.toUTCString(); var ifModifiedSince = "If-Modified-Since".toLowerCase(); response.setHeader("Last-Modified", lastModified); if (ext.match(config.Expires.fileMatch)) { var expires = new Date(); expires.setTime(expires.getTime() + config.Expires.maxAge * 1000); response.setHeader("Expires", expires.toUTCString()); response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge); } if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, "Not Modified"); response.end(); } else { fs.readFile(realPath, "binary", function(err, file) { if (err) { response.writeHead(500, "Internal Server Error", {'Content-Type': 'text/plain'}); response.end(err); } else { response.writeHead(200, "Ok"); response.write(file, "binary"); response.end(); } }); } }); } }); });
curl --header "If-Modified-Since: Fri, 11 Nov 2011 19:14:51 GMT" -i http://localhost:8000
HTTP/1.1 304 Not Modified Content-Type: text/html Last-Modified: Fri, 11 Nov 2011 19:14:51 GMT Connection: keep-alive
var zlib = require("zlib");
exports.Compress = { match: /css|js|html/ig };
var raw = fs.createReadStream(realPath); var acceptEncoding = request.headers['accept-encoding'] || ""; var matched = ext.match(config.Compress.match); if (matched && acceptEncoding.match(/\bgzip\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'gzip'}); raw.pipe(zlib.createGzip()).pipe(response); } else if (matched && acceptEncoding.match(/\bdeflate\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'deflate'}); raw.pipe(zlib.createDeflate()).pipe(response); } else { response.writeHead(200, "Ok"); raw.pipe(response); }
var server = http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname; var realPath = path.join("assets", pathname); path.exists(realPath, function (exists) { if (!exists) { response.writeHead(404, "Not Found", {'Content-Type': 'text/plain'}); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; var contentType = mime[ext] || "text/plain"; response.setHeader("Content-Type", contentType); fs.stat(realPath, function (err, stat) { var lastModified = stat.mtime.toUTCString(); var ifModifiedSince = "If-Modified-Since".toLowerCase(); response.setHeader("Last-Modified", lastModified); if (ext.match(config.Expires.fileMatch)) { var expires = new Date(); expires.setTime(expires.getTime() + config.Expires.maxAge * 1000); response.setHeader("Expires", expires.toUTCString()); response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge); } if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, "Not Modified"); response.end(); } else { var raw = fs.createReadStream(realPath); var acceptEncoding = request.headers['accept-encoding'] || ""; var matched = ext.match(config.Compress.match); if (matched && acceptEncoding.match(/\bgzip\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'gzip'}); raw.pipe(zlib.createGzip()).pipe(response); } else if (matched && acceptEncoding.match(/\bdeflate\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'deflate'}); raw.pipe(zlib.createDeflate()).pipe(response); } else { response.writeHead(200, "Ok"); raw.pipe(response); } } }); } }); });
# curl -i http://localhost:8000/../app.js HTTP/1.1 200 Ok Content-Type: text/javascript Last-Modified: Thu, 10 Nov 2011 17:16:51 GMT Expires: Sat, 10 Nov 2012 04:59:27 GMT Cache-Control: max-age=31536000 Connection: keep-alive Transfer-Encoding: chunked var PORT = 8000; var http = require("http"); var url = require("url"); var fs = require("fs"); var path = require("path"); var mime = require("./mime").types;
var realPath = path.join("assets", path.normalize(pathname.replace(/\.\./g, "")));
exports.Welcome = { file: "index.html" };
if (pathname.slice(-1) === "/") { pathname = pathname + config.Welcome.file; }
if (stats.isDirectory()) { realPath = path.join(realPath, "/", config.Welcome.file); }
var server = http.createServer(function(request, response) { var pathname = url.parse(request.url).pathname; if (pathname.slice(-1) === "/") { pathname = pathname + config.Welcome.file; } var realPath = path.join("assets", path.normalize(pathname.replace(/\.\./g, ""))); var pathHandle = function (realPath) { fs.stat(realPath, function (err, stats) { if (err) { response.writeHead(404, "Not Found", {'Content-Type': 'text/plain'}); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { if (stats.isDirectory()) { realPath = path.join(realPath, "/", config.Welcome.file); pathHandle(realPath); } else { var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; var contentType = mime[ext] || "text/plain"; response.setHeader("Content-Type", contentType); var lastModified = stats.mtime.toUTCString(); var ifModifiedSince = "If-Modified-Since".toLowerCase(); response.setHeader("Last-Modified", lastModified); if (ext.match(config.Expires.fileMatch)) { var expires = new Date(); expires.setTime(expires.getTime() + config.Expires.maxAge * 1000); response.setHeader("Expires", expires.toUTCString()); response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge); } if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, "Not Modified"); response.end(); } else { var raw = fs.createReadStream(realPath); var acceptEncoding = request.headers['accept-encoding'] || ""; var matched = ext.match(config.Compress.match); if (matched && acceptEncoding.match(/\bgzip\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'gzip'}); raw.pipe(zlib.createGzip()).pipe(response); } else if (matched && acceptEncoding.match(/\bdeflate\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'deflate'}); raw.pipe(zlib.createDeflate()).pipe(response); } else { response.writeHead(200, "Ok"); raw.pipe(response); } } } } }); }; pathHandle(realPath); });
ranges-specifier = byte-ranges-specifier byte-ranges-specifier = bytes-unit "=" byte-range-set byte-range-set = 1#( byte-range-spec | suffix-byte-range-spec ) byte-range-spec = first-byte-pos "-" [last-byte-pos] first-byte-pos = 1*DIGIT last-byte-pos = 1*DIGIT
var utils = require("./utils");
exports.parseRange = function (str, size) { if (str.indexOf(",") != -1) { return; } var range = str.split("-"), start = parseInt(range[0], 10), end = parseInt(range[1], 10); // Case: -100 if (isNaN(start)) { start = size - end; end = size - 1; // Case: 100- } else if (isNaN(end)) { end = size - 1; } // Invalid if (isNaN(start) || isNaN(end) || start > end || end > size) { return; } return {start: start, end: end}; };
response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + stats.size); response.setHeader("Content-Length", (range.end - range.start + 1));
var compressHandle = function (raw, statusCode, reasonPhrase) { var stream = raw; var acceptEncoding = request.headers['accept-encoding'] || ""; var matched = ext.match(config.Compress.match); if (matched && acceptEncoding.match(/\bgzip\b/)) { response.setHeader("Content-Encoding", "gzip"); stream = raw.pipe(zlib.createGzip()); } else if (matched && acceptEncoding.match(/\bdeflate\b/)) { response.setHeader("Content-Encoding", "deflate"); stream = raw.pipe(zlib.createDeflate()); } response.writeHead(statusCode, reasonPhrase); stream.pipe(response); }; if (request.headers["range"]) { var range = utils.parseRange(request.headers["range"], stats.size); if (range) { response.setHeader("Content-Range", "bytes " + range.start + "-" + range.end + "/" + stats.size); response.setHeader("Content-Length", (range.end - range.start + 1)); var raw = fs.createReadStream(realPath, {"start": range.start, "end": range.end}); compressHandle(raw, 206, "Partial Content"); } else { response.removeHeader("Content-Length"); response.writeHead(416, "Request Range Not Satisfiable"); response.end(); } } else { var raw = fs.createReadStream(realPath); compressHandle(raw, 200, "Ok"); }
HTTP/1.1 206 Partial Content Server: Node/V5 Accept-Ranges: bytes Content-Type: text/html Content-Length: 21 Last-Modified: Fri, 11 Nov 2011 19:14:51 GMT Content-Range: bytes 0-20/54 Connection: keep-aliveI
HTTP/1.1 416 Request Range Not Satisfiable Server: Node/V5 Accept-Ranges: bytes Content-Type: text/html Last-Modified: Fri, 11 Nov 2011 19:14:51 GMT Connection: keep-alive Transfer-Encoding: chunked
Server: nginx
response.setHeader("Server", "Node/V5");