UNPKG

@nodefony/http-bundle

Version:

Nodefony Framework Bundle HTTP

377 lines (352 loc) 11.6 kB
const mime = require("mime"); // eslint-disable-next-line max-lines-per-function nodefony.register.call(nodefony.context, "http", () => { const Http = class httpContext extends nodefony.Context { constructor (container, request, response, type) { super(container, request, response, type); this.uploadService = this.get("upload"); this.requestSettings = this.kernelHttp.settings.request; this.queryStringParser = this.kernelHttp.settings.queryString; this.isElectron = this.kernel.isElectron; this.protocol = type === "HTTP2" ? "2.0" : "1.1"; this.pushAllowed = false; if (this.type === "HTTP2") { this.request = new nodefony.http2Request(request, this); this.response = new nodefony.http2Response(response, container); } else { this.request = new nodefony.Request(request, this); this.response = new nodefony.Response(response, container); } this.csrf = null; this.parseCookies(); this.cookieSession = this.getCookieSession(this.sessionService.settings.name); this.once("onRequestEnd", () => { try { if (this.isRedirect) { return this.send(); } } catch (e) { return this.kernelHttp.onError(this.container, e); // this.fire("onError", this.container, e); } }); this.method = this.request.getMethod(); this.isAjax = this.request.isAjax(); this.isHtml = this.request.acceptHtml; this.setDefaultContentType(); this.isRedirect = false; this.sended = false; this.showDebugBar = true; this.timeoutExpired = false; this.promise = null; this.timeoutid = null; this.profiling = null; this.url = url.format(this.request.url); this.scheme = this.request.url.protocol.replace(":", ""); if (this.request.url.port) { this.port = this.request.url.port; } else { this.port = this.scheme === "https" ? 443 : 80; } 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(); this.remoteAddress = this.request.remoteAddress; this.once("onTimeout", () => { let error = null; if (this.response.stream) { // traff 408 reload page htpp2 loop error = new nodefony.httpError("Gateway Timeout", 504, this.container); } else { error = new nodefony.httpError("Request Timeout", 408, this.container); } return this.kernelHttp.onError(this.container, error); // this.fire("onError", this.container, error); }); // case proxy this.proxy = null; if (request.headers["x-forwarded-for"]) { if (request.headers["x-forwarded-proto"]) { this.type = request.headers["x-forwarded-proto"].toUpperCase(); } this.proxy = { proxyServer: request.headers["x-forwarded-server"] || "unknown", proxyProto: request.headers["x-forwarded-proto"], proxyScheme: request.headers["x-forwarded-scheme"], proxyPort: request.headers["x-forwarded-port"], proxyFor: request.headers["x-forwarded-for"], proxyHost: request.headers["x-forwarded-host"], proxyUri: request.headers["x-original-uri"], proxyRealIp: request.headers["x-real-ip"], proxyVia: request.headers.via || "unknown" }; this.log(`PROXY REQUEST x-forwarded VIA : ${this.proxy.proxyVia}`, "DEBUG"); } /* if (this.security) { this.crossDomain = this.isCrossDomain(); }*/ } getRemoteAddress () { return this.request.getRemoteAddress(); } getHost () { return this.request.getHost(); } getHostName () { return this.request.getHostName(); } getUserAgent () { return this.request.getUserAgent(); } getMethod () { return this.request.getMethod(); } setCsrfToken (name, options) { this.csrf = this.csrfService.createCsrfToken(name, options, this); return this.csrf; } handle (data) { return new Promise((resolve, reject) => { try { if (this.isRedirect) { return resolve(this.send()); } this.setParameters("query.get", this.request.queryGet); if (this.request.queryPost) { this.setParameters("query.post", this.request.queryPost); } if (this.request.queryFile) { this.setParameters("query.files", this.request.queryFile); } this.setParameters("query.request", this.request.query); this.locale = this.translation.handle(); if (!this.resolver) { this.resolver = this.router.resolve(this); } // WARNING EVENT KERNEL this.fire("onRequest", this, this.resolver); this.kernel.fire("onRequest", this, this.resolver); if (this.resolver.resolve) { const ret = this.resolver.callController(data); // timeout response after callController (to change timeout in action ) if (this.timeoutid !== null) { this.timeoutExpired = false; clearTimeout(this.timeoutid); } if (this.response.response) { if (this.response.stream) { this.timeoutid = this.response.response.setTimeout(this.response.timeout, () => { this.timeoutExpired = true; this.fire("onTimeout", this); }); } else { this.timeoutid = this.response.response.setTimeout(this.response.timeout, () => { this.timeoutExpired = true; this.fire("onTimeout", this); }); } } return resolve(ret); } const error = new Error(""); error.code = 404; return reject(error); } catch (e) { return reject(e); } }); } clean () { if (this.timeoutid !== null) { clearTimeout(this.timeoutid); } this.request.clean(); this.response.clean(); this.request = null; this.response = null; delete this.response; delete this.request; this.proxy = null; delete this.proxy; this.uploadService = null; delete this.uploadService; this.container.clean(); super.clean(); } send (data, type) { if (this.sended || this.finished) { return new Promise((resolve, reject) => { reject(new Error("Already sended")); }); } return this.saveSession() .then(async (session) => { if (session) { this.log(`SAVE SESSION ID : ${session.id}`, "DEBUG"); } await this.fireAsync("onSend", this.response, this); this.writeHead(); if (!this.isRedirect) { return this.write(data, type); } return this.response.end(); }) .catch(async (error) => { this.log(error, "ERROR"); this.writeHead(error.code || 500); this.write(data, type); return error; }); } writeHead (statusCode, headers) { // cookies if (this.response) { this.response.setCookies(); this.response.writeHead(statusCode, headers); } } async write (data, encoding) { if (this.finished || this.sended) { return; } if (!this.profiler) { if (this.profiling) { await this.fireAsync("onSendMonitoring", this.response, this); } /* * WRITE RESPONSE */ this.sended = true; this.response.send(data, encoding); // END REQUEST return this.close(); } await this.fireAsync("onSendMonitoring", this.response, this); return this; } flush (data, encoding) { return this.response.flush(data, encoding); } async close () { await this.fireAsync("onClose", this); // END REQUEST this.profiling = null; delete this.profiling; return this.response.end(); } redirect (Url, status, headers) { if (typeof Url === "object") { return this.response.redirect(url.format(Url), status, headers); } return this.response.redirect(Url, status, headers); } redirectHttps (status, headers) { if (this.session) { this.session.setFlashBag("redirect", "HTTPS"); } let urlExtend = null; if (this.proxy) { urlExtend = { protocol: "https", href: "", host: "" }; } else { urlExtend = { protocol: "https", port: this.kernelHttp.httpsPort || 443, href: "", host: "" }; } const urlChange = nodefony.extend({}, this.request.url, urlExtend); const newUrl = url.format(urlChange); return this.redirect(newUrl, status, headers); } redirectHttp (status, headers) { if (this.session) { this.session.setFlashBag("redirect", "HTTP"); } let urlExtend = null; if (this.proxy) { urlExtend = { protocol: "http", href: "", host: "" }; } else { urlExtend = { protocol: "http", port: this.kernelHttp.httpPort || 80, href: "", host: "" }; } const urlChange = nodefony.extend({}, this.request.url, urlExtend); const newUrl = url.format(urlChange); return this.redirect(newUrl, status, headers); } setContextJson (encoding) { if (!encoding) { encoding = "charset=utf-8"; } else { encoding = `charset=${encoding}`; } this.isJson = true; const type = mime.getType("json"); if (this.method !== "websoket") { if (this.response) { this.response.setHeader("Content-Type", `${type}; ${encoding}`); } } } setContextHtml (encoding) { if (!encoding) { encoding = "charset=utf-8"; } else { encoding = `charset=${encoding}`; } this.isJson = false; const type = mime.getType("html"); if (this.method !== "websoket") { if (this.response) { this.response.setHeader("Content-Type", `${type}; ${encoding}`); } } } setXjson (xjson) { switch (nodefony.typeOf(xjson)) { case "object": this.response.setHeader("X-Json", JSON.stringify(xjson)); return xjson; case "string": this.response.setHeader("X-Json", xjson); return JSON.parse(xjson); case "Error": if (typeof xjson.message === "object") { this.response.setHeader("X-Json", JSON.stringify(xjson.message)); return xjson.message; } this.response.setHeader("X-Json", xjson.message); return { error: xjson.message }; break; } } setDefaultContentType () { if (this.isHtml) { this.response.setContentType("html", "utf-8"); } else if (this.request.accepts("json")) { this.isJson = true; this.response.setContentType("json", "utf-8"); } } }; return Http; });