Revision control
Copy as Markdown
Other Tools
/* 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,
/**
* A mock server to mimic operations with Graph API.
*/
export class GraphServer {
/**
* The mock HTTP server to use to handle Graph requests.
*
* @type {HttpServer}
* @name GraphServer.httpServer
*/
#httpServer;
/**
* The username that must be supplied on requests to this server if HTTP
* basic authentication is used.
*
* @type {string}
* @name GraphServer.username
* @private
*/
#username;
/**
* The password that must be supplied on requests to this server if HTTP
* basic authentication is used.
*
* @type {string}
* @name GraphServer.password
* @private
*/
#password;
/**
* The port for the server to listen on.
*
* @type {number}
* @name GraphServer.listenPort
* @private
*/
#listenPort;
constructor(username = "user", password = "password", listenPort = -1) {
this.#httpServer = new HttpServer();
this.#httpServer.registerPrefixHandler("/", (request, response) => {
try {
this.#dispatchResource(request, response);
} catch (e) {
console.error("Error when processing request:", e);
throw e;
}
});
this.#username = username;
this.#password = password;
this.#listenPort = listenPort;
}
/**
* Start listening for requests.
*/
start() {
this.#httpServer.start(this.#listenPort);
}
/**
* Stop listening for requests.
*/
stop() {
this.#httpServer.stop();
}
/**
* Return the port the server is listening on. This might not match the value
* passed to the class constructor.
*/
get port() {
return this.#httpServer.identity.primaryPort;
}
/**
* Dispatch a request to the appropriate resource handler based on the
* request API path and method.
*
* @param {nsIHttpRequest} request
* @param {nsIHttpResponse} response
*/
#dispatchResource(request, response) {
// Try to read the value of the `Authorization` header.
if (request.hasHeader("Authorization")) {
const authorizationValue = request.getHeader("Authorization");
if (authorizationValue.startsWith("Basic ")) {
const [username, password] = atob(
authorizationValue.substring(6)
).split(":");
if (username != this.#username || password != this.#password) {
response.setStatusLine("1.1", 401, "Unauthorized");
response.setHeader("WWW-Authenticate", `Basic realm="test"`);
return;
}
}
}
const resourcePath = request.path;
let responseJsonObject = {};
if (resourcePath === "/me") {
responseJsonObject = this.#me();
} else {
throw new Error(`Unexpected Graph resource: ${resourcePath}`);
}
// Send the response.
const responseBody = JSON.stringify(responseJsonObject);
response.bodyOutputStream.write(responseBody, responseBody.length);
}
/**
* Handle the /me resource.
*
* @returns {object}
*/
#me() {
return {
businessPhones: ["+1 425 555 0109"],
displayName: "Adele Vance",
givenName: "Adele",
jobTitle: "Retail Manager",
mail: "AdeleV@contoso.com",
mobilePhone: "+1 425 555 0109",
officeLocation: "18/2111",
preferredLanguage: "en-US",
surname: "Vance",
userPrincipalName: "AdeleV@contoso.com",
id: "87d349ed-44d7-43e1-9a83-5f2406dee5bd",
};
}
}