gecko/dom/downloads/tests/serve_file.sjs

108 lines
2.9 KiB
JavaScript

// Serves a file with a given mime type and size at an optionally given rate.
function getQuery(request) {
var query = {};
request.queryString.split('&').forEach(function (val) {
var [name, value] = val.split('=');
query[name] = unescape(value);
});
return query;
}
// Timer used to handle the request response.
var timer = null;
function handleResponse() {
// Is this a rate limited response?
if (this.state.rate > 0) {
// Calculate how many bytes we have left to send.
var bytesToWrite = this.state.totalBytes - this.state.sentBytes;
// Do we have any bytes left to send? If not we'll just fall thru and
// cancel our repeating timer and finalize the response.
if (bytesToWrite > 0) {
// Figure out how many bytes to send, based on the rate limit.
bytesToWrite =
(bytesToWrite > this.state.rate) ? this.state.rate : bytesToWrite;
for (let i = 0; i < bytesToWrite; i++) {
this.response.write("0");
}
// Update the number of bytes we've sent to the client.
this.state.sentBytes += bytesToWrite;
// Wait until the next call to do anything else.
return;
}
}
else {
// Not rate limited, write it all out.
for (let i = 0; i < this.state.totalBytes; i++) {
this.response.write("0");
}
}
// Finalize the response.
this.response.finish();
// All done sending, go ahead and cancel our repeating timer.
timer.cancel();
}
function handleRequest(request, response) {
var query = getQuery(request);
// Default values for content type, size and rate.
var contentType = "text/plain";
var size = 1024;
var rate = 0;
// optional content type to be used by our response.
if ("contentType" in query) {
contentType = query["contentType"];
}
// optional size (in bytes) for generated file.
if ("size" in query) {
size = parseInt(query["size"]);
}
// optional rate (in bytes/s) at which to send the file.
if ("rate" in query) {
rate = parseInt(query["rate"]);
}
// The context for the responseHandler.
var context = {
response: response,
state: {
contentType: contentType,
totalBytes: size,
sentBytes: 0,
rate: rate
}
};
// The notify implementation for the timer.
context.notify = handleResponse.bind(context);
timer =
Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
// sending at a specific rate requires our response to be asynchronous so
// we handle all requests asynchronously. See handleResponse().
response.processAsync();
// generate the content.
response.setHeader("Content-Type", contentType, false);
response.setHeader("Content-Length", size.toString(), false);
// initialize the timer and start writing out the response.
timer.initWithCallback(context,
1000,
Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
}