RetroZilla/netwerk/test/unit/head_http_server.js
2015-10-20 23:03:22 -04:00

156 lines
4.4 KiB
JavaScript

// vim:set sw=2 ts=2 sts=2 cin:
function nsTestServ(port) {
dump(">>> creating nsTestServ instance\n");
this.port = port;
}
nsTestServ.prototype =
{
handler: {
// This function generates standard headers for a specific HTTP result
// code. The code can include text like "Not Found". The return value does
// not include a terminating empty line, so new headers can be added after
// it.
headers: function(code) {
return "HTTP/1.0 " + code + "\r\n" +
"Connection: close\r\n" +
"Server: Necko unit test server\r\n" +
"Content-Type: text/plain\r\n";
},
// This object contains the handlers for the various request URIs
// numeric properties are HTTP result codes
400: function(stream)
{
var response = this.headers("400 Bad Request") +
"\r\n" +
"Bad request";
stream.write(response, response.length);
},
404: function(stream)
{
var response = this.headers("404 Not Found") +
"\r\n" +
"No such path";
stream.write(response, response.length);
},
"/": function(stream)
{
var response = this.headers("200 OK") +
"\r\n" +
"200 OK";
stream.write(response, response.length);
},
"/redirect": function(stream)
{
var response = this.headers("301 Moved Permanently") +
"Location: http://localhost:4444/\r\n" +
"\r\n" +
"Moved";
stream.write(response, response.length);
},
"/redirectfile": function(stream)
{
var response = this.headers("301 Moved Permanently") +
"Location: file:///\r\n" +
"\r\n" +
"Moved to a file URI";
stream.write(response, response.length);
}
},
QueryInterface: function(iid)
{
if (iid.equals(Components.interfaces.nsIServerSocketListener) ||
iid.equals(Components.interfaces.nsISupports))
return this;
Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
return null;
},
/* this function is called when we receive a new connection */
onSocketAccepted: function(serverSocket, clientSocket)
{
dump(">>> accepted connection on "+clientSocket.host+":"+clientSocket.port+"\n");
const nsITransport = Components.interfaces.nsITransport;
var input = clientSocket.openInputStream(nsITransport.OPEN_BLOCKING, 0, 0);
var output = clientSocket.openOutputStream(nsITransport.OPEN_BLOCKING, 0, 0);
var request = this.parseInput(input);
// Strip away query parameters, then unescape the request
var path = request.replace(/\?.*/, "");
try {
path = decodeURI(path);
} catch (ex) {
path = 400;
}
if (path in this.handler)
this.handler[path](output);
else
this.handler[404](output);
input.close();
output.close();
},
onStopListening: function(serverSocket, status)
{
dump(">>> shutting down server socket\n");
},
startListening: function()
{
const nsIServerSocket = Components.interfaces.nsIServerSocket;
const SERVERSOCKET_CONTRACTID = "@mozilla.org/network/server-socket;1";
var socket = Components.classes[SERVERSOCKET_CONTRACTID].createInstance(nsIServerSocket);
socket.init(this.port, true /* loopback only */, 5);
dump(">>> listening on port "+socket.port+"\n");
socket.asyncListen(this);
},
parseInput: function(input)
{
// We read the input line by line. The first line tells us the requested
// path.
var is = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
is.init(input, "ISO-8859-1", 1024, 0xFFFD);
var lis =
is.QueryInterface(Components.interfaces.nsIUnicharLineInputStream);
var line = {};
var cont = lis.readLine(line);
var request = line.value.split(/ +/);
if (request[0] != "GET" && request[0] != "POST")
return 400;
// This server doesn't support HTTP 0.9
if (request[2] != "HTTP/1.0" && request[2] != "HTTP/1.1")
return 400;
while (line.value != "") {
lis.readLine(line);
}
if (request[1][0] != "/")
return 400;
return request[1];
}
}
function start_server(port) {
new nsTestServ(port).startListening();
}