@nodefony/http-bundle
Version:
Nodefony Framework Bundle HTTP
297 lines (278 loc) • 10.1 kB
JavaScript
nodefony.register.call(nodefony.context, "websocket", () => {
const onClose = function (reasonCode, description) {
this.log(
`${clc.cyan("URL")} : ${this.url} ${clc.cyan("FROM")} : ${this.remoteAddress} ${clc.cyan("ORIGIN")} : ${this.originUrl.host} ${clc.cyan("Description")} : ${description} `,
"INFO",
`${this.type} ${clc.magenta(reasonCode)} CLOSE ${this.method}`
);
if (this.connection.state !== "closed") {
try {
this.response.drop(reasonCode, description);
} catch (e) {
// this.log('CLOSE : ' + this.remoteAddress + " ORIGIN : " + this.origin + " " + e.message, "ERROR");
this.log(
`${clc.cyan("URL")} : ${this.url} ${clc.cyan("FROM")} : ${this.remoteAddress} ${clc.cyan("ORIGIN")} : ${this.originUrl.host} ${clc.cyan("error")} : ${e.message} `,
"ERROR",
`${this.type} CLOSE ${clc.red(this.method)}`
);
}
this.fire("onClose", reasonCode, description, this.connection);
} else {
this.fire("onClose", reasonCode, description, this.connection);
}
this.fire("onFinish", this, reasonCode, description);
};
const websocket = class websocketContext extends nodefony.Context {
constructor (container, request, type) {
super(container, request, null, type);
this.protocol = type === "WEBSOCKET SECURE" ? "wss" : "ws";
this.scheme = type === "WEBSOCKET SECURE" ? "wss" : "ws";
this.isJson = true;
this.method = this.getMethod();
this.response = new nodefony.wsResponse(null, this.container, this.type);
this.request = request;
this.request.method = this.method;
this.remoteAddress = this.request.remoteAddress;
this.origin = this.request.origin;
this.acceptedProtocol = request.httpRequest.headers["sec-websocket-protocol"] || null;
this.request.url = url.parse(`${this.scheme}://${this.request.host}`);
this.request.url.hash = this.request.resourceURL.hash;
this.request.url.search = this.request.resourceURL.search;
this.request.url.query = this.request.resourceURL.query;
this.request.query = this.request.resourceURL.query;
this.request.url.pathname = this.request.resourceURL.pathname;
this.request.url.path = this.request.resourceURL.path;
this.url = url.format(this.request.url);
this.port = this.request.url.port;
// this.nodefonyId = null;
this.parseCookies();
this.cookieSession = this.getCookieSession(this.sessionService.settings.name);
try {
this.originUrl = url.parse(this.request.origin);
} catch (e) {
this.originUrl = url.parse(this.url);
}
// domain
this.domain = this.getHostName();
this.validDomain = this.isValidDomain();
// LISTEN EVENTS
this.rejected = false;
this.request.on("requestRejected", () => {
this.rejected = true;
});
// case proxy
this.proxy = null;
if (this.request.httpRequest.headers["x-forwarded-for"]) {
this.proxy = {
proxyServer: this.request.httpRequest.headers["x-forwarded-server"],
proxyProto: this.request.httpRequest.headers["x-forwarded-proto"],
proxyPort: this.request.httpRequest.headers["x-forwarded-port"],
proxyFor: this.request.httpRequest.headers["x-forwarded-for"],
proxyHost: this.request.httpRequest.headers["x-forwarded-host"],
proxyVia: this.request.httpRequest.headers.via
};
this.log(`PROXY WEBSOCKET REQUEST x-forwarded VIA : ${this.proxy.proxyVia}`, "DEBUG");
}
this.crossDomain = this.isCrossDomain();
}
logRequest (httpError, acceptedProtocol) {
if (httpError) {
// return httpError.logger();
return this.log(
`${clc.cyan("URL")} : ${this.url} ${clc.cyan("FROM")} : ${this.remoteAddress} ${clc.cyan("ORIGIN")} : ${this.originUrl.host}
${httpError.toString()}`,
"ERROR",
`${this.type} ${clc.magenta(this.response.statusCode)} ${clc.red(this.method)}`
);
}
return this.log(
`${clc.cyan("URL")} : ${this.url} ${clc.cyan("Accept-Protocol")} : ${acceptedProtocol || "*"} ${clc.cyan("FROM")} : ${this.remoteAddress} ${clc.cyan("ORIGIN")} : ${this.originUrl.host}`,
"INFO",
`${this.type} ${clc.magenta(this.response.statusCode)} ${this.method}`
);
/* return this.log(`FROM : ${this.remoteAddress} ORIGIN : ${this.originUrl.host} URL : ${this.url}`,
"INFO",
(this.isAjax ? `${this.type} AJAX REQUEST ${this.method}` : `${this.type} ${this.method}`));*/
}
connect () {
return new Promise((resolve, reject) => {
try {
if (this.rejected) {
return;
}
let acceptedProtocol = null;
if (this.resolver) {
acceptedProtocol = this.resolver.acceptedProtocol;
}
this.response.setCookies();
this.connection = this.request.accept(acceptedProtocol, this.origin, this.response.cookiesToSet);
this.response.setConnection(this.connection);
this.connection.on("close", onClose.bind(this));
this.requestEnded = true;
this.fire("onConnect", this, this.connection);
// LISTEN EVENTS SOCKET
this.connection.on("message", this.handleMessage.bind(this));
this.logRequest(null, acceptedProtocol);
return resolve(this.connection);
} catch (e) {
return reject(e);
}
});
}
getRemoteAddress () {
return this.remoteAddress;
}
getHost () {
return this.request.httpRequest.headers.host;
}
getHostName () {
return this.request.url.hostname;
}
getUserAgent () {
return this.request.httpRequest.headers["user-agent"];
}
getMethod () {
return "WEBSOCKET";
}
clean () {
this.request = null;
delete this.request;
if (this.response) {
this.response.clean();
}
this.response = null;
this.container.clean();
super.clean();
}
handleMessage (message) {
this.response.body = message;
try {
if (!this.resolver) {
this.resolver = this.router.resolve(this);
} else {
try {
this.resolver.match(this.resolver.route, this);
} catch (e) {
this.request.reject();
throw e;
}
}
this.fire("onMessage", message, this, "RECEIVE");
if (this.resolver.resolve) {
/* try {
if( message.utf8Data){
let result = JSON.parse(message.utf8Data);
if (result.nodefonyId) {
this.nodefonyId = {
id: result.nodefonyId,
timeout: result.timeout,
timeoutid: result.timeoutid
}
delete result.nodefonyId;
delete result.timeout;
delete result.timeoutid;
message.utf8Data = result.stringify(result);
return this.resolver.callController(message);
}
}
} catch (e) {
return this.resolver.callController(message);
}*/
return this.resolver.callController(message);
} else if (!this.rejected) {
this.request.reject();
this.rejected = true;
}
} catch (e) {
throw e;
}
}
handle (data) {
if (this.rejected) {
return;
}
try {
this.locale = this.translation.handle();
if (!this.resolver) {
this.resolver = this.router.resolve(this);
} else {
try {
this.resolver.match(this.resolver.route, this);
} catch (e) {
if (!this.rejected) {
this.request.reject();
this.rejected = true;
}
throw e;
}
}
// WARNING EVENT KERNEL
this.fire("onRequest", this, this.resolver);
this.kernel.fire("onRequest", this, this.resolver);
if (this.resolver.resolve) {
return this.saveSession()
.then((session) => {
if (session) {
this.log(`SAVE SESSION ID : ${session.id}`, "DEBUG");
}
return this.resolver.callController(data || null);
})
.catch((error) => {
if (!this.rejected) {
if (this.request) {
if (this.request._resolved) {
return this.close(parseInt(error.code, 10) + 3000, error.message);
}
this.request.reject();
}
this.rejected = true;
}
});
} else if (!this.rejected) {
this.request.reject();
this.rejected = true;
}
} catch (e) {
throw e;
}
}
handleError (container, error) {
this.log(`Message : ${error.message}`, "ERROR");
}
send (data, type) {
if (this.response) {
if (!data) {
data = this.response.body;
}
if (data) {
this.fire("onMessage", data, this, "SEND");
this.fire("onSend", data, this);
return this.response.send(data, type);
}
}
return null;
}
broadcast (data, type) {
if (this.response) {
if (!data) {
data = this.response.body;
}
if (data) {
this.fire("onMessage", data, this, "BROADCAST");
this.fire("onBroadcast", data, this);
return this.response.broadcast(data, type);
}
}
return null;
}
close (reasonCode, description) {
if (this.response) {
return this.response.close(reasonCode, description);
}
}
drop (reasonCode, description) {
return this.response.drop(reasonCode, description);
}
};
return websocket;
});