UNPKG

@leansdk/leanrc

Version:

LeanRC is a MVC framework for creating graceful applications

535 lines (484 loc) 14.5 kB
(function() { // This file is part of LeanRC. // LeanRC is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // LeanRC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // You should have received a copy of the GNU Lesser General Public License // along with LeanRC. If not, see <https://www.gnu.org/licenses/>. // net = require 'net' # will be used only 'isIP' function // contentType = require 'content-type' // stringify = require('url').format // parse = require 'parseurl' // qs = require 'querystring' // typeis = require 'type-is' // fresh = require 'fresh' /* Идеи взяты из https://github.com/koajs/koa/blob/master/lib/request.js */ module.exports = function(Module) { var AnyT, ContextInterface, CoreObject, FuncG, MaybeG, NilT, Request, RequestInterface, SwitchInterface, UnionG, _; ({ AnyT, NilT, FuncG, UnionG, MaybeG, RequestInterface, SwitchInterface, ContextInterface, CoreObject, Utils: {_} } = Module.prototype); return Request = (function() { class Request extends CoreObject {}; Request.inheritProtected(); Request.implements(RequestInterface); Request.module(Module); Request.public({ req: Object // native request object }, { get: function() { return this.ctx.req; } }); Request.public({ switch: SwitchInterface }, { get: function() { return this.ctx.switch; } }); Request.public({ ctx: ContextInterface }); // @public baseUrl: String # под вопросом? // @public database: String # возможно это тоже надо получать из метода из отдельного модуля // @public pathname: String // @public pathParams: Object # вынести в отдельный модуль, который будет подключаться как миксин, а в чейнинге будет вызваться метод, который будет распарсивать парамсы // @public cookie: Function, // default: (name, options)-> Request.public({ body: MaybeG(AnyT) // тело должен предоставлять миксин из отдельного модуля }); Request.public({ header: Object }, { get: function() { return this.headers; } }); Request.public({ headers: Object }, { get: function() { return this.req.headers; } }); Request.public({ originalUrl: String }, { get: function() { return this.ctx.originalUrl; } }); Request.public({ url: String }, { get: function() { return this.req.url; }, set: function(url) { return this.req.url = url; } }); Request.public({ origin: String }, { get: function() { return `${this.protocol}://${this.host}`; } }); Request.public({ href: String }, { get: function() { if (/^https?:\/\//i.test(this.originalUrl)) { return this.originalUrl; } return this.origin + this.originalUrl; } }); Request.public({ method: String }, { get: function() { return this.req.method; }, set: function(method) { return this.req.method = method; } }); Request.public({ path: String }, { get: function() { var parse; parse = require('parseurl'); return parse(this.req).pathname; }, set: function(path) { var parse, stringify, url; parse = require('parseurl'); url = parse(this.req); if (url.pathname === path) { return; } url.pathname = path; url.path = null; stringify = require('url').format; return this.url = stringify(url); } }); Request.public({ query: Object }, { get: function() { var qs; qs = require('querystring'); return qs.parse(this.querystring); }, set: function(obj) { var qs; qs = require('querystring'); this.querystring = qs.stringify(obj); return obj; } }); Request.public({ querystring: String }, { get: function() { var parse, ref; if (this.req == null) { return ''; } parse = require('parseurl'); return (ref = parse(this.req).query) != null ? ref : ''; }, set: function(str) { var parse, stringify, url; parse = require('parseurl'); url = parse(this.req); if (url.search === `?${str}`) { return; } url.search = str; url.path = null; stringify = require('url').format; return this.url = stringify(url); } }); Request.public({ search: String }, { get: function() { if (!this.querystring) { return ''; } return `?${this.querystring}`; }, set: function(str) { return this.querystring = str; } }); Request.public({ host: String }, { get: function() { var host, trustProxy; ({trustProxy} = this.ctx.switch.configs); host = trustProxy && this.get('X-Forwarded-Host'); host = host || this.get('Host'); if (!host) { return ''; } return host.split(/\s*,\s*/)[0]; } }); // port отсутствует в интерфейсе koa - возможно лучше его и здесь не делать, чтобы не ломать интерфейс koa // @public port: Number, // get: -> // host = @host // port = if host // host.split(':')[1] // unless port // port = if @protocol is 'https' // 443 // else // 80 // Number port Request.public({ hostname: String }, { get: function() { var host; host = this.host; if (!host) { return ''; } return host.split(':')[0]; } }); Request.public({ fresh: Boolean }, { get: function() { var fresh, method, s; method = this.method; s = this.ctx.status; // GET or HEAD for weak freshness validation only if ('GET' !== method && 'HEAD' !== method) { return false; } // 2xx or 304 as per rfc2616 14.26 if ((s >= 200 && s < 300) || 304 === s) { fresh = require('fresh'); return fresh(this.headers, this.ctx.response.headers); } return false; } }); Request.public({ stale: Boolean }, { get: function() { return !this.fresh; } }); Request.public({ idempotent: Boolean }, { get: function() { var methods; methods = ['GET', 'HEAD', 'PUT', 'DELETE', 'OPTIONS', 'TRACE']; return _.includes(methods, this.method); } }); Request.public({ socket: MaybeG(Object) }, { get: function() { return this.req.socket; } }); Request.public({ charset: String }, { get: function() { var contentType, err, ref, type; type = this.get('Content-Type'); if (type == null) { return ''; } try { contentType = require('content-type'); type = contentType.parse(type); } catch (error) { err = error; return ''; } return (ref = type.parameters.charset) != null ? ref : ''; } }); Request.public({ length: Number }, { get: function() { var contentLength; if ((contentLength = this.get('Content-Length')) != null) { if (contentLength === '') { return 0; } return ~~Number(contentLength); } else { return 0; } } }); Request.public({ protocol: String }, { get: function() { var proto, ref, trustProxy; ({trustProxy} = this.ctx.switch.configs); if ((ref = this.socket) != null ? ref.encrypted : void 0) { return 'https'; } if (this.req.secure) { return 'https'; } if (!trustProxy) { return 'http'; } proto = this.get('X-Forwarded-Proto'); if (!proto) { proto = 'http'; } return proto.split(/\s*,\s*/)[0]; } }); // xhr отсутствует в интерфейсе koa - возможно лучше его и здесь не делать, чтобы не ломать интерфейс koa // @public xhr: Boolean, // get: -> // 'xmlhttprequest' is String(@headers['X-Requested-With']).toLowerCase() Request.public({ secure: Boolean }, { get: function() { return this.protocol === 'https'; } }); Request.public({ ip: String }); Request.public({ ips: Array }, { get: function() { var trustProxy, value; ({trustProxy} = this.ctx.switch.configs); value = this.get('X-Forwarded-For'); if (trustProxy && value) { return value.split(/\s*,\s*/); } else { return []; } } }); Request.public({ subdomains: Array }, { get: function() { var hostname, net, offset; ({ subdomainOffset: offset } = this.ctx.switch.configs); hostname = this.hostname; net = require('net'); if (net.isIP(hostname) !== 0) { return []; } return hostname.split('.').reverse().slice(offset != null ? offset : 0); } }); Request.public({ accepts: FuncG([MaybeG(UnionG(String, Array))], UnionG(String, Array, Boolean)) }, { default: function(...args) { return this.ctx.accept.types(...args); } }); Request.public({ acceptsCharsets: FuncG([MaybeG(UnionG(String, Array))], UnionG(String, Array)) }, { default: function(...args) { return this.ctx.accept.charsets(...args); } }); Request.public({ acceptsEncodings: FuncG([MaybeG(UnionG(String, Array))], UnionG(String, Array)) }, { default: function(...args) { return this.ctx.accept.encodings(...args); } }); Request.public({ acceptsLanguages: FuncG([MaybeG(UnionG(String, Array))], UnionG(String, Array)) }, { default: function(...args) { return this.ctx.accept.languages(...args); } }); Request.public({ 'is': FuncG([UnionG(String, Array)], UnionG(String, Boolean, NilT)) }, { default: function(...args) { var typeis, types; [types] = args; typeis = require('type-is'); if (!types) { return typeis(this.req); } if (!_.isArray(types)) { types = args; } return typeis(this.req, types); } }); Request.public({ type: String }, { get: function() { var type; type = this.get('Content-Type'); if (type == null) { return ''; } return type.split(';')[0]; } }); Request.public({ get: FuncG(String, String) }, { default: function(field) { //@headers[name] var ref, ref1, ref2, req; req = this.req; switch (field = field.toLowerCase()) { case 'referer': case 'referrer': return (ref = (ref1 = req.headers.referrer) != null ? ref1 : req.headers.referer) != null ? ref : ''; default: return (ref2 = req.headers[field]) != null ? ref2 : ''; } } }); // @public inspect: FuncG([], Object), // default: -> // return unless @req // @toJSON() // @public toJSON: FuncG([], Object), // default: -> _.pick @, ['method', 'url', 'header'] Request.public(Request.static(Request.async({ restoreObject: Function }, { default: function*() { throw new Error(`restoreObject method not supported for ${this.name}`); } }))); Request.public(Request.static(Request.async({ replicateObject: Function }, { default: function*() { throw new Error(`replicateObject method not supported for ${this.name}`); } }))); Request.public({ init: FuncG(ContextInterface) }, { default: function(context) { var ref, ref1, ref2, ref3; this.super(); this.ctx = context; this.ip = (ref = (ref1 = (ref2 = this.ips[0]) != null ? ref2 : (ref3 = this.req.socket) != null ? ref3.remoteAddress : void 0) != null ? ref1 : this.req.remoteAddress) != null ? ref : ''; } }); Request.initialize(); return Request; }).call(this); }; }).call(this);