src/server/protocol/http.js
const JsonRpcServerProtocol = require("./base");
const { errorToStatus } = require("../../util/constants");
/**
* Creates instance of HttpServerProtocol
* @extends JsonRpcServerProtocol
*
*/
class HttpServerProtocol extends JsonRpcServerProtocol {
/**
* As well as all the params and properties in [JsonRpcServerProtocol]{@link JsonRpcServerProtocol}
* the following properties are available.
*
* @property {class} response HTTP response object
* @property {object} headers={"Content-Type":"application/json"} HTTP response headers
*/
constructor(factory, client, response, version, delimiter) {
super(factory, client, version, delimiter);
this.response = response;
this.headers = {
"Content-Type": "application/json"
};
this.status = null;
}
/**
* Send message to the client.
*
* @param {string} message Stringified JSON-RPC message object
*/
writeToClient(message) {
const json = JSON.parse(message);
if (!this.status) {
// set the status code if it has not been overwritten
if (json.error) {
this.setResponseStatus({
errorCode: json.error.code
});
} else {
this.status = 200;
}
}
this.response.writeHead(this.status, this.headers).end(message);
}
/**
* Calls `emit` on factory with the event name being `message.method` and
* the data being `message`.
*
* Responds to client with 204 status.
*
* @param {object} message JSON-RPC message object
*/
gotNotification(message) {
super.gotNotification(message.method, message);
this.setResponseStatus({
notification: true
});
this.response.writeHead(this.status, this.headers).end();
}
/**
* Registers the `event` data listener when client connects.
*
* Pushes received data into `messageBuffer` and calls
* [_waitForData]{@link JsonRpcServerProtocol#_waitForData}.
*
* The HTTP server does not use the delimiter since the completion of a request indicates
* the end of data.
*
* @extends JsonRpcServerProtocol.clientConnected
*/
clientConnected() {
this.client.on(this.event, (chunk) => {
this.messageBuffer.push(chunk);
});
this.client.on("end", () => {
this._validateData(this.messageBuffer.emptyBuffer());
this.factory._removeFromArray(this, this.factory.pendingRequests);
});
}
/**
* Set response status code
*
* @param {object} options
* @param {number} options.errorCode The JSON-RPC error code to lookup a corresponding status code for
* @param {number} options.status The HTTP status code (will override the errorCode)
* @param {boolean} options.notification Inidicate if setting header for notification (will override other options with 204 status)
*/
setResponseStatus({ errorCode, status, notification }) {
this.status = 200;
if (errorCode) {
this.status = errorToStatus[String(errorCode)];
}
if (status) {
this.status = status;
}
if (notification) {
this.status = 204; // notification responses must be 204 per spec, so no point in allowing an override
}
}
}
module.exports = HttpServerProtocol;