Skip to content

Instantly share code, notes, and snippets.

@kevinswiber
Created August 5, 2012 21:28
Show Gist options
  • Save kevinswiber/3267194 to your computer and use it in GitHub Desktop.
Save kevinswiber/3267194 to your computer and use it in GitHub Desktop.
A minimal Web server implementation in Node.js.
var url = require('url');
var webserver = require('./webserver');
var routes = {};
routes['/'] = {
get: function(request, response) {
var pathname = url.parse(request.url).pathname;
if (pathname !== '/') {
response.notFound();
return;
}
response.ok({ 'Content-Type': 'text/plain' }, 'Hello, server!');
}
};
routes['/about'] = {
get: function(request, response) {
response.ok({ 'Content-Type': 'text/plain' }, 'This is me!');
}
};
routes['/articles'] = {
get: function(request, response) {
var pathname = url.parse(request.url).pathname;
var parts = pathname.split('/').splice(2);
if (parts.length > 1) {
response.notFound();
return;
} else if (parts.length === 1) {
var id = parts[0];
response.ok({ 'Content-Type': 'text/plain' }, 'id: ' + id);
return;
}
response.end('get articles');
},
post: function(request, response) {
request.on('data', function(data) {
var requestBody = data.toString();
if (requestBody === 'yello') {
response.ok({ 'Content-Type': 'text/plain' }, 'what\'s up?!');
}
});
setTimeout(function() { response.end('Timeout!'); }, 1000);
}
};
routes['/articles/fury'] = {
get: function(request, response) {
response.end('FURY!!!!!!!!!11');
},
del: function(request, response) {
response.end('FURY GONE!!!!!!!');
}
};
webserver.serve(routes);
exports.mixin = function(obj) {
obj.ok = function(headers, body) {
send(this, { status: 200, headers: headers, body: body });
};
obj.notFound = function() {
var options = {
status: 404,
headers: { 'Content-Type': 'text/plain' },
body: 'Not Found'
};
send(this, options);
};
obj.methodNotAllowed = function() {
var options = {
status: 405,
headers: { 'Content-Type': 'text/plain' },
body: 'Method Not Allowed'
};
send(this, options);
};
};
function send(response, options) {
var status = options.status;
var headers = options.headers || {};
var body = options.body;
if (!headers['Content-Length'] && body) {
headers['Content-Length'] = body.length;
}
response.writeHead(status, headers);
response.end(body);
}
var http = require('http');
var url = require('url');
var responseHelpers = require('./helpers/response');
exports.serve = function(map) {
var validUris = [];
var validMethods = {};
validUris = Object.keys(map);
validUris.sort(function(a,b) {
if (a.length > b.length) {
return - 1;
} else if (a.length < b.length) {
return 1;
}
return 0;
});
validUris.forEach(function(uri, index) {
validMethods[uri] = Object.keys(map[uri]);
});
http.createServer(function(request, response) {
responseHelpers.mixin(response);
var pathname = url.parse(request.url).pathname;
var method = request.method.toLowerCase();
if (method === 'delete') {
method = 'del';
}
var matchedUri;
validUris.forEach(function(uri) {
if (!matchedUri && pathname.indexOf(uri) === 0) {
matchedUri = uri;
}
});
if (!matchedUri) {
response.notFound();
return;
}
if (validMethods[matchedUri].indexOf(method) === -1) {
response.methodNotAllowed();
return;
}
var resource = map[matchedUri];
if (resource[method]) {
resource[method].call(resource, request, response);
}
}).listen(process.env.PORT || 3000);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment