Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Tests that the scheme, host, and port of the server are correctly recorded
* and used in HTTP requests and responses.
*/
"use strict";
const PORT = 4444;
const FAKE_PORT_ONE = 8888;
const FAKE_PORT_TWO = 8889;
let srv, id;
add_task(async function run_test1() {
dump("*** run_test1");
srv = createServer();
srv.registerPathHandler("/http/1.0-request", http10Request);
srv.registerPathHandler("/http/1.1-good-host", http11goodHost);
srv.registerPathHandler(
"/http/1.1-good-host-wacky-port",
http11goodHostWackyPort
);
srv.registerPathHandler("/http/1.1-ip-host", http11ipHost);
srv.start(FAKE_PORT_ONE);
id = srv.identity;
// The default location is http://localhost:PORT, where PORT is whatever you
// provided when you started the server. http://127.0.0.1:PORT is also part
// of the default set of locations.
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, FAKE_PORT_ONE);
Assert.ok(id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_ONE));
// This should be a nop.
id.add("http", "localhost", FAKE_PORT_ONE);
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, FAKE_PORT_ONE);
Assert.ok(id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_ONE));
// Change the primary location and make sure all the getters work correctly.
id.setPrimary("http", "127.0.0.1", FAKE_PORT_ONE);
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "127.0.0.1");
Assert.equal(id.primaryPort, FAKE_PORT_ONE);
Assert.ok(id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_ONE));
// Okay, now remove the primary location -- we fall back to the original
// location.
id.remove("http", "127.0.0.1", FAKE_PORT_ONE);
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, FAKE_PORT_ONE);
Assert.ok(id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
// You can't remove every location -- try this and the original default
// location will be silently readded.
id.remove("http", "localhost", FAKE_PORT_ONE);
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, FAKE_PORT_ONE);
Assert.ok(id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
// Okay, now that we've exercised that behavior, shut down the server and
// restart it on the correct port, to exercise port-changing behaviors at
// server start and stop.
await new Promise(resolve => srv.stop(resolve));
});
add_task(async function run_test_2() {
dump("*** run_test_2");
// Our primary location is gone because it was dependent on the port on which
// the server was running.
checkPrimariesThrow(id);
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
srv.start(FAKE_PORT_TWO);
// We should have picked up http://localhost:8889 as our primary location now
// that we've restarted.
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, FAKE_PORT_TWO);
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
Assert.ok(id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_TWO));
// Now we're going to see what happens when we shut down with a primary
// location that wasn't a default. That location should persist, and the
// default we remove should still not be present.
id.setPrimary("http", "example.com", FAKE_PORT_TWO);
Assert.ok(id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_TWO));
Assert.ok(id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
id.remove("http", "localhost", FAKE_PORT_TWO);
Assert.ok(id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(id.has("http", "127.0.0.1", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
id.remove("http", "127.0.0.1", FAKE_PORT_TWO);
Assert.ok(id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
await new Promise(resolve => srv.stop(resolve));
});
add_task(async function run_test_3() {
dump("*** run_test_3");
// Only the default added location disappears; any others stay around,
// possibly as the primary location. We may have removed the default primary
// location, but the one we set manually should persist here.
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "example.com");
Assert.equal(id.primaryPort, FAKE_PORT_TWO);
Assert.ok(id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
srv.start(PORT);
// Starting always adds HTTP entries for 127.0.0.1:port and localhost:port.
Assert.ok(id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
Assert.ok(id.has("http", "localhost", PORT));
Assert.ok(id.has("http", "127.0.0.1", PORT));
// Remove the primary location we'd left set from last time.
id.remove("http", "example.com", FAKE_PORT_TWO);
// Default-port behavior testing requires the server responds to requests
// claiming to be on one such port.
id.add("http", "localhost", 80);
// Make sure we don't have anything lying around from running on either the
// first or the second port -- all we should have is our generated default,
// plus the additional port to test "portless" hostport variants.
Assert.ok(id.has("http", "localhost", 80));
Assert.equal(id.primaryScheme, "http");
Assert.equal(id.primaryHost, "localhost");
Assert.equal(id.primaryPort, PORT);
Assert.ok(id.has("http", "localhost", PORT));
Assert.ok(id.has("http", "127.0.0.1", PORT));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_ONE));
Assert.ok(!id.has("http", "example.com", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "localhost", FAKE_PORT_TWO));
Assert.ok(!id.has("http", "127.0.0.1", FAKE_PORT_TWO));
// Okay, finally done with identity testing. Our primary location is the one
// we want it to be, so we're off!
await new Promise(resolve =>
runRawTests(tests, resolve, idx => dump(`running test no ${idx}`))
);
// Finally shut down the server.
await new Promise(resolve => srv.stop(resolve));
});
/** *******************
* UTILITY FUNCTIONS *
*********************/
/**
* Verifies that all .primary* getters on a server identity correctly throw
* NS_ERROR_NOT_INITIALIZED.
*
* @param aId : nsIHttpServerIdentity
* the server identity to test
*/
function checkPrimariesThrow(aId) {
let threw = false;
try {
aId.primaryScheme;
} catch (e) {
threw = e.result === Cr.NS_ERROR_NOT_INITIALIZED;
}
Assert.ok(threw);
threw = false;
try {
aId.primaryHost;
} catch (e) {
threw = e.result === Cr.NS_ERROR_NOT_INITIALIZED;
}
Assert.ok(threw);
threw = false;
try {
aId.primaryPort;
} catch (e) {
threw = e.result === Cr.NS_ERROR_NOT_INITIALIZED;
}
Assert.ok(threw);
}
/**
* Utility function to check for a 400 response.
*/
function check400(aData) {
let iter = LineIterator(aData);
// Status-Line
let { value: firstLine } = iter.next();
Assert.equal(firstLine.substring(0, HTTP_400_LEADER_LENGTH), HTTP_400_LEADER);
}
/** *************
* BEGIN TESTS *
***************/
const HTTP_400_LEADER = "HTTP/1.1 400 ";
const HTTP_400_LEADER_LENGTH = HTTP_400_LEADER.length;
var test, data;
var tests = [];
// HTTP/1.0 request, to ensure we see our default scheme/host/port
function http10Request(request, response) {
writeDetails(request, response);
response.setStatusLine("1.0", 200, "TEST PASSED");
}
data = "GET /http/1.0-request HTTP/1.0\r\n\r\n";
function check10(aData) {
let iter = LineIterator(aData);
// Status-Line
Assert.equal(iter.next().value, "HTTP/1.0 200 TEST PASSED");
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check10);
tests.push(test);
// HTTP/1.1 request, no Host header, expect a 400 response
// eslint-disable-next-line no-useless-concat
data = "GET /http/1.1-request HTTP/1.1\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, wrong host, expect a 400 response
data =
// eslint-disable-next-line no-useless-concat
"GET /http/1.1-request HTTP/1.1\r\n" + "Host: not-localhost\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, wrong host/right port, expect a 400 response
data =
"GET /http/1.1-request HTTP/1.1\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Host header has host but no port, expect a 400 response
// eslint-disable-next-line no-useless-concat
data = "GET /http/1.1-request HTTP/1.1\r\n" + "Host: 127.0.0.1\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong port, expect a 400 response
data =
"GET http://127.0.0.1/http/1.1-request HTTP/1.1\r\n" +
"Host: 127.0.0.1\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong port, expect a 400 response
data =
"Host: localhost:31337\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, Request-URI has wrong scheme, expect a 400 response
data =
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, correct Host header, expect handler's response
function http11goodHost(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data =
// eslint-disable-next-line no-useless-concat
"GET /http/1.1-good-host HTTP/1.1\r\n" + "Host: localhost:4444\r\n" + "\r\n";
function check11goodHost(aData) {
let iter = LineIterator(aData);
// Status-Line
Assert.equal(iter.next().value, "HTTP/1.1 200 TEST PASSED");
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body = [
"Method: GET",
"Path: /http/1.1-good-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, Host header is secondary identity
function http11ipHost(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data =
// eslint-disable-next-line no-useless-concat
"GET /http/1.1-ip-host HTTP/1.1\r\n" + "Host: 127.0.0.1:4444\r\n" + "\r\n";
function check11ipHost(aData) {
let iter = LineIterator(aData);
// Status-Line
Assert.equal(iter.next().value, "HTTP/1.1 200 TEST PASSED");
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body = [
"Method: GET",
"Path: /http/1.1-ip-host",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11ipHost);
tests.push(test);
// HTTP/1.1 request, absolute path, accurate Host header
// reusing previous request handler so not defining a new one
data =
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, inaccurate Host header
// reusing previous request handler so not defining a new one
data =
"Host: localhost:1234\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, different inaccurate Host header
// reusing previous request handler so not defining a new one
data =
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.1 request, absolute path, yet another inaccurate Host header
// reusing previous request handler so not defining a new one
data =
"Host: yippity-skippity\r\n" +
"\r\n";
function checkInaccurate(aData) {
check11goodHost(aData);
// dynamism setup
srv.identity.setPrimary("http", "127.0.0.1", 4444);
}
test = new RawTest("localhost", PORT, data, checkInaccurate);
tests.push(test);
// HTTP/1.0 request, absolute path, different inaccurate Host header
// reusing previous request handler so not defining a new one
data =
"GET /http/1.0-request HTTP/1.0\r\n" +
"Host: not-localhost:4444\r\n" +
"\r\n";
function check10ip(aData) {
let iter = LineIterator(aData);
// Status-Line
Assert.equal(iter.next().value, "HTTP/1.0 200 TEST PASSED");
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body = [
"Method: GET",
"Path: /http/1.0-request",
"Query: ",
"Version: 1.0",
"Scheme: http",
"Host: 127.0.0.1",
"Port: 4444",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check10ip);
tests.push(test);
// HTTP/1.1 request, Host header with implied port
function http11goodHostWackyPort(request, response) {
writeDetails(request, response);
response.setStatusLine("1.1", 200, "TEST PASSED");
}
data =
"GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n";
function check11goodHostWackyPort(aData) {
let iter = LineIterator(aData);
// Status-Line
Assert.equal(iter.next().value, "HTTP/1.1 200 TEST PASSED");
skipHeaders(iter);
// Okay, next line must be the data we expected to be written
let body = [
"Method: GET",
"Path: /http/1.1-good-host-wacky-port",
"Query: ",
"Version: 1.1",
"Scheme: http",
"Host: localhost",
"Port: 80",
];
expectLines(iter, body);
}
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, Host header with wacky implied port
data =
"GET /http/1.1-good-host-wacky-port HTTP/1.1\r\n" +
"Host: localhost:\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with implied port
data =
"Host: localhost\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with wacky implied port
data =
"Host: localhost\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, absolute URI with explicit implied port, ignored Host
data =
"Host: who-cares\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHostWackyPort);
tests.push(test);
// HTTP/1.1 request, a malformed Request-URI
data =
"GET is-this-the-real-life-is-this-just-fantasy HTTP/1.1\r\n" +
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, a malformed Host header
// eslint-disable-next-line no-useless-concat
data = "GET /http/1.1-request HTTP/1.1\r\n" + "Host: la la la\r\n" + "\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, a malformed Host header but absolute URI, 5.2 sez fine
data =
"Host: la la la\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check11goodHost);
tests.push(test);
// HTTP/1.0 request, absolute URI, but those aren't valid in HTTP/1.0
data =
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, absolute URI with unrecognized host
data =
"Host: not-localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);
// HTTP/1.1 request, absolute URI with unrecognized host (but not in Host)
data =
"Host: localhost:4444\r\n" +
"\r\n";
test = new RawTest("localhost", PORT, data, check400);
tests.push(test);