diff options
Diffstat (limited to 'netwerk/test/unit/test_oblivious_http.js')
-rw-r--r-- | netwerk/test/unit/test_oblivious_http.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_oblivious_http.js b/netwerk/test/unit/test_oblivious_http.js new file mode 100644 index 0000000000..027426038d --- /dev/null +++ b/netwerk/test/unit/test_oblivious_http.js @@ -0,0 +1,206 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { HttpServer } = ChromeUtils.importESModule( + "resource://testing-common/httpd.sys.mjs" +); + +class ObliviousHttpTestRequest { + constructor(method, uri, headers, content) { + this.method = method; + this.uri = uri; + this.headers = headers; + this.content = content; + } +} + +class ObliviousHttpTestResponse { + constructor(status, headers, content) { + this.status = status; + this.headers = headers; + this.content = content; + } +} + +class ObliviousHttpTestCase { + constructor(request, response) { + this.request = request; + this.response = response; + } +} + +add_task(async function test_oblivious_http() { + let testcases = [ + new ObliviousHttpTestCase( + new ObliviousHttpTestRequest( + "GET", + NetUtil.newURI("https://example.com"), + { "X-Some-Header": "header value" }, + "" + ), + new ObliviousHttpTestResponse(200, {}, "Hello, World!") + ), + new ObliviousHttpTestCase( + new ObliviousHttpTestRequest( + "POST", + NetUtil.newURI("http://example.test"), + { "X-Some-Header": "header value", "X-Some-Other-Header": "25" }, + "Posting some content..." + ), + new ObliviousHttpTestResponse( + 418, + { "X-Teapot": "teapot" }, + "I'm a teapot" + ) + ), + new ObliviousHttpTestCase( + new ObliviousHttpTestRequest( + "GET", + NetUtil.newURI("http://example.test/404"), + { "X-Some-Header": "header value", "X-Some-Other-Header": "25" }, + "" + ), + undefined // 404 relay + ), + ]; + + for (let testcase of testcases) { + await run_one_testcase(testcase); + } +}); + +async function run_one_testcase(testcase) { + let ohttp = Cc["@mozilla.org/network/oblivious-http;1"].getService( + Ci.nsIObliviousHttp + ); + let ohttpServer = ohttp.server(); + + let httpServer = new HttpServer(); + httpServer.registerPathHandler("/", function (request, response) { + let inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance( + Ci.nsIScriptableInputStream + ); + inputStream.init(request.bodyInputStream); + let requestBody = inputStream.readBytes(inputStream.available()); + let ohttpResponse = ohttpServer.decapsulate(stringToBytes(requestBody)); + let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService( + Ci.nsIBinaryHttp + ); + let decodedRequest = bhttp.decodeRequest(ohttpResponse.request); + equal(decodedRequest.method, testcase.request.method); + equal(decodedRequest.scheme, testcase.request.uri.scheme); + equal(decodedRequest.authority, testcase.request.uri.hostPort); + equal(decodedRequest.path, testcase.request.uri.pathQueryRef); + for ( + let i = 0; + i < decodedRequest.headerNames.length && + i < decodedRequest.headerValues.length; + i++ + ) { + equal( + decodedRequest.headerValues[i], + testcase.request.headers[decodedRequest.headerNames[i]] + ); + } + equal(bytesToString(decodedRequest.content), testcase.request.content); + + let responseHeaderNames = ["content-type"]; + let responseHeaderValues = ["text/plain"]; + for (let headerName of Object.keys(testcase.response.headers)) { + responseHeaderNames.push(headerName); + responseHeaderValues.push(testcase.response.headers[headerName]); + } + let binaryResponse = new BinaryHttpResponse( + testcase.response.status, + responseHeaderNames, + responseHeaderValues, + stringToBytes(testcase.response.content) + ); + let responseBytes = bhttp.encodeResponse(binaryResponse); + let encResponse = ohttpResponse.encapsulate(responseBytes); + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Content-Type", "message/ohttp-res", false); + response.write(bytesToString(encResponse)); + }); + httpServer.start(-1); + + let ohttpService = Cc[ + "@mozilla.org/network/oblivious-http-service;1" + ].getService(Ci.nsIObliviousHttpService); + let relayURI = NetUtil.newURI( + `http://localhost:${httpServer.identity.primaryPort}/` + ); + if (!testcase.response) { + relayURI = NetUtil.newURI( + `http://localhost:${httpServer.identity.primaryPort}/404` + ); + } + let obliviousHttpChannel = ohttpService + .newChannel(relayURI, testcase.request.uri, ohttpServer.encodedConfig) + .QueryInterface(Ci.nsIHttpChannel); + for (let headerName of Object.keys(testcase.request.headers)) { + obliviousHttpChannel.setRequestHeader( + headerName, + testcase.request.headers[headerName], + false + ); + } + if (testcase.request.method == "POST") { + let uploadChannel = obliviousHttpChannel.QueryInterface( + Ci.nsIUploadChannel2 + ); + ok(uploadChannel); + let bodyStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( + Ci.nsIStringInputStream + ); + bodyStream.setData( + testcase.request.content, + testcase.request.content.length + ); + uploadChannel.explicitSetUploadStream( + bodyStream, + null, + -1, + testcase.request.method, + false + ); + } + let response = await new Promise((resolve, reject) => { + NetUtil.asyncFetch(obliviousHttpChannel, function (inputStream, result) { + let scriptableInputStream = Cc[ + "@mozilla.org/scriptableinputstream;1" + ].createInstance(Ci.nsIScriptableInputStream); + scriptableInputStream.init(inputStream); + try { + // If decoding failed just return undefined. + inputStream.available(); + } catch (e) { + resolve(undefined); + return; + } + let responseBody = scriptableInputStream.readBytes( + inputStream.available() + ); + resolve(responseBody); + }); + }); + if (testcase.response) { + equal(response, testcase.response.content); + for (let headerName of Object.keys(testcase.response.headers)) { + equal( + obliviousHttpChannel.getResponseHeader(headerName), + testcase.response.headers[headerName] + ); + } + } else { + let relayChannel = obliviousHttpChannel.QueryInterface( + Ci.nsIObliviousHttpChannel + ).relayChannel; + equal(relayChannel.responseStatus, 404); + } + await new Promise((resolve, reject) => { + httpServer.stop(resolve); + }); +} |