1 /* Any copyright is dedicated to the Public Domain.
2 * https://creativecommons.org/publicdomain/zero/1.0/ */
6 const { HttpServer
} = ChromeUtils
.importESModule(
7 "resource://testing-common/httpd.sys.mjs"
10 class ObliviousHttpTestRequest
{
11 constructor(method
, uri
, headers
, content
) {
14 this.headers
= headers
;
15 this.content
= content
;
19 class ObliviousHttpTestResponse
{
20 constructor(status
, headers
, content
) {
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() {
36 new ObliviousHttpTestCase(
37 new ObliviousHttpTestRequest(
39 NetUtil
.newURI("https://example.com"),
40 { "X-Some-Header": "header value" },
43 new ObliviousHttpTestResponse(200, {}, "Hello, World!")
45 new ObliviousHttpTestCase(
46 new ObliviousHttpTestRequest(
48 NetUtil
.newURI("http://example.test"),
49 { "X-Some-Header": "header value", "X-Some-Other-Header": "25" },
50 "Posting some content..."
52 new ObliviousHttpTestResponse(
54 { "X-Teapot": "teapot" },
58 new ObliviousHttpTestCase(
59 new ObliviousHttpTestRequest(
61 NetUtil
.newURI("http://example.test"),
62 { "X-Some-Header": "header value", "X-Some-Other-Header": "25" },
63 "Putting some content..."
65 new ObliviousHttpTestResponse(
67 { "X-Teapot": "teapot" },
71 new ObliviousHttpTestCase(
72 new ObliviousHttpTestRequest(
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
);
87 async
function run_one_testcase(testcase
) {
88 let ohttp
= Cc
["@mozilla.org/network/oblivious-http;1"].getService(
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(
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
);
111 i
< decodedRequest
.headerNames
.length
&&
112 i
< decodedRequest
.headerValues
.length
;
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
,
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(
159 testcase
.request
.headers
[headerName
],
163 if (testcase
.request
.method
== "POST" || testcase
.request
.method
== "PUT") {
164 let uploadChannel
= obliviousHttpChannel
.QueryInterface(
168 let bodyStream
= Cc
["@mozilla.org/io/string-input-stream;1"].createInstance(
169 Ci
.nsIStringInputStream
171 bodyStream
.setByteStringData(testcase
.request
.content
);
172 uploadChannel
.explicitSetUploadStream(
176 testcase
.request
.method
,
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
);
187 // If decoding failed just return undefined.
188 inputStream
.available();
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
)) {
203 obliviousHttpChannel
.getResponseHeader(headerName
),
204 testcase
.response
.headers
[headerName
]
208 let relayChannel
= obliviousHttpChannel
.QueryInterface(
209 Ci
.nsIObliviousHttpChannel
211 equal(relayChannel
.responseStatus
, 404);
213 await
new Promise(resolve
=> {
214 httpServer
.stop(resolve
);