Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / netwerk / test / unit / test_oblivious_http.js
blob9b9915b4acdde72c0c4f498bd18a43186fb38513
1 /* Any copyright is dedicated to the Public Domain.
2 * https://creativecommons.org/publicdomain/zero/1.0/ */
4 "use strict";
6 const { HttpServer } = ChromeUtils.importESModule(
7 "resource://testing-common/httpd.sys.mjs"
8 );
10 class ObliviousHttpTestRequest {
11 constructor(method, uri, headers, content) {
12 this.method = method;
13 this.uri = uri;
14 this.headers = headers;
15 this.content = content;
19 class ObliviousHttpTestResponse {
20 constructor(status, headers, content) {
21 this.status = status;
22 this.headers = headers;
23 this.content = content;
27 class ObliviousHttpTestCase {
28 constructor(request, response) {
29 this.request = request;
30 this.response = response;
34 add_task(async function test_oblivious_http() {
35 let testcases = [
36 new ObliviousHttpTestCase(
37 new ObliviousHttpTestRequest(
38 "GET",
39 NetUtil.newURI("https://example.com"),
40 { "X-Some-Header": "header value" },
43 new ObliviousHttpTestResponse(200, {}, "Hello, World!")
45 new ObliviousHttpTestCase(
46 new ObliviousHttpTestRequest(
47 "POST",
48 NetUtil.newURI("http://example.test"),
49 { "X-Some-Header": "header value", "X-Some-Other-Header": "25" },
50 "Posting some content..."
52 new ObliviousHttpTestResponse(
53 418,
54 { "X-Teapot": "teapot" },
55 "I'm a teapot"
58 new ObliviousHttpTestCase(
59 new ObliviousHttpTestRequest(
60 "PUT",
61 NetUtil.newURI("http://example.test"),
62 { "X-Some-Header": "header value", "X-Some-Other-Header": "25" },
63 "Putting some content..."
65 new ObliviousHttpTestResponse(
66 418,
67 { "X-Teapot": "teapot" },
68 "I'm a teapot"
71 new ObliviousHttpTestCase(
72 new ObliviousHttpTestRequest(
73 "GET",
74 NetUtil.newURI("http://example.test/404"),
75 { "X-Some-Header": "header value", "X-Some-Other-Header": "25" },
78 undefined // 404 relay
82 for (let testcase of testcases) {
83 await run_one_testcase(testcase);
85 });
87 async function run_one_testcase(testcase) {
88 let ohttp = Cc["@mozilla.org/network/oblivious-http;1"].getService(
89 Ci.nsIObliviousHttp
91 let ohttpServer = ohttp.server();
93 let httpServer = new HttpServer();
94 httpServer.registerPathHandler("/", function (request, response) {
95 let inputStream = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
96 Ci.nsIScriptableInputStream
98 inputStream.init(request.bodyInputStream);
99 let requestBody = inputStream.readBytes(inputStream.available());
100 let ohttpResponse = ohttpServer.decapsulate(stringToBytes(requestBody));
101 let bhttp = Cc["@mozilla.org/network/binary-http;1"].getService(
102 Ci.nsIBinaryHttp
104 let decodedRequest = bhttp.decodeRequest(ohttpResponse.request);
105 equal(decodedRequest.method, testcase.request.method);
106 equal(decodedRequest.scheme, testcase.request.uri.scheme);
107 equal(decodedRequest.authority, testcase.request.uri.hostPort);
108 equal(decodedRequest.path, testcase.request.uri.pathQueryRef);
109 for (
110 let i = 0;
111 i < decodedRequest.headerNames.length &&
112 i < decodedRequest.headerValues.length;
115 equal(
116 decodedRequest.headerValues[i],
117 testcase.request.headers[decodedRequest.headerNames[i]]
120 equal(bytesToString(decodedRequest.content), testcase.request.content);
122 let responseHeaderNames = ["content-type"];
123 let responseHeaderValues = ["text/plain"];
124 for (let headerName of Object.keys(testcase.response.headers)) {
125 responseHeaderNames.push(headerName);
126 responseHeaderValues.push(testcase.response.headers[headerName]);
128 let binaryResponse = new BinaryHttpResponse(
129 testcase.response.status,
130 responseHeaderNames,
131 responseHeaderValues,
132 stringToBytes(testcase.response.content)
134 let responseBytes = bhttp.encodeResponse(binaryResponse);
135 let encResponse = ohttpResponse.encapsulate(responseBytes);
136 response.setStatusLine(request.httpVersion, 200, "OK");
137 response.setHeader("Content-Type", "message/ohttp-res", false);
138 response.write(bytesToString(encResponse));
140 httpServer.start(-1);
142 let ohttpService = Cc[
143 "@mozilla.org/network/oblivious-http-service;1"
144 ].getService(Ci.nsIObliviousHttpService);
145 let relayURI = NetUtil.newURI(
146 `http://localhost:${httpServer.identity.primaryPort}/`
148 if (!testcase.response) {
149 relayURI = NetUtil.newURI(
150 `http://localhost:${httpServer.identity.primaryPort}/404`
153 let obliviousHttpChannel = ohttpService
154 .newChannel(relayURI, testcase.request.uri, ohttpServer.encodedConfig)
155 .QueryInterface(Ci.nsIHttpChannel);
156 for (let headerName of Object.keys(testcase.request.headers)) {
157 obliviousHttpChannel.setRequestHeader(
158 headerName,
159 testcase.request.headers[headerName],
160 false
163 if (testcase.request.method == "POST" || testcase.request.method == "PUT") {
164 let uploadChannel = obliviousHttpChannel.QueryInterface(
165 Ci.nsIUploadChannel2
167 ok(uploadChannel);
168 let bodyStream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
169 Ci.nsIStringInputStream
171 bodyStream.setByteStringData(testcase.request.content);
172 uploadChannel.explicitSetUploadStream(
173 bodyStream,
174 null,
176 testcase.request.method,
177 false
180 let response = await new Promise(resolve => {
181 NetUtil.asyncFetch(obliviousHttpChannel, function (inputStream) {
182 let scriptableInputStream = Cc[
183 "@mozilla.org/scriptableinputstream;1"
184 ].createInstance(Ci.nsIScriptableInputStream);
185 scriptableInputStream.init(inputStream);
186 try {
187 // If decoding failed just return undefined.
188 inputStream.available();
189 } catch (e) {
190 resolve(undefined);
191 return;
193 let responseBody = scriptableInputStream.readBytes(
194 inputStream.available()
196 resolve(responseBody);
199 if (testcase.response) {
200 equal(response, testcase.response.content);
201 for (let headerName of Object.keys(testcase.response.headers)) {
202 equal(
203 obliviousHttpChannel.getResponseHeader(headerName),
204 testcase.response.headers[headerName]
207 } else {
208 let relayChannel = obliviousHttpChannel.QueryInterface(
209 Ci.nsIObliviousHttpChannel
210 ).relayChannel;
211 equal(relayChannel.responseStatus, 404);
213 await new Promise(resolve => {
214 httpServer.stop(resolve);