PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/node_modules/browser-sync/lib/server/utils.js

https://gitlab.com/minhaj_mimo/weatherApp
JavaScript | 397 lines | 255 code | 47 blank | 95 comment | 22 complexity | 703807781a7d4e8aed7ee352bb7d263e MD5 | raw file
  1. "use strict";
  2. var fs = require("fs");
  3. var filePath = require("path");
  4. var connect = require("connect");
  5. var Immutable = require("immutable");
  6. var http = require("http");
  7. var https = require("https");
  8. var Map = require("immutable").Map;
  9. var fromJS = require("immutable").fromJS;
  10. var List = require("immutable").List;
  11. var snippet = require("./../snippet").utils;
  12. var _ = require("./../../lodash.custom");
  13. var serveStatic = require("serve-static");
  14. var logger = require("../logger");
  15. var snippetUtils = require("../snippet").utils;
  16. var lrSnippet = require("resp-modifier");
  17. var utils = require("../utils");
  18. var serverUtils = {
  19. /**
  20. * @param options
  21. * @returns {{key, cert}}
  22. */
  23. getKeyAndCert: function (options) {
  24. return {
  25. key: fs.readFileSync(options.getIn(["https", "key"]) || filePath.join(__dirname, "certs/server.key")),
  26. cert: fs.readFileSync(options.getIn(["https", "cert"]) || filePath.join(__dirname, "certs/server.crt")),
  27. ca: fs.readFileSync(options.getIn(["https", "ca"]) || filePath.join(__dirname, "certs/server.csr")),
  28. passphrase: options.getIn(["https", "passphrase"]) || ""
  29. };
  30. },
  31. /**
  32. * @param filePath
  33. * @returns {{pfx}}
  34. */
  35. getPFX: function (filePath) {
  36. return {
  37. pfx: fs.readFileSync(filePath)
  38. };
  39. },
  40. /**
  41. * Get either an http or https server
  42. */
  43. getServer: function (app, options) {
  44. return {
  45. server: (function () {
  46. if (options.get("scheme") === "https") {
  47. var pfxPath = options.getIn(["https", "pfx"]);
  48. return pfxPath ?
  49. https.createServer(serverUtils.getPFX(pfxPath), app) :
  50. https.createServer(serverUtils.getKeyAndCert(options), app);
  51. }
  52. return http.createServer(app);
  53. })(),
  54. app: app
  55. };
  56. },
  57. getMiddlewares: function (bs) {
  58. var clientJs = bs.pluginManager.hook("client:js", {
  59. port: bs.options.get("port"),
  60. options: bs.options
  61. });
  62. var scripts = bs.pluginManager.get("client:script")(
  63. bs.options.toJS(),
  64. clientJs,
  65. "middleware"
  66. );
  67. var defaultMiddlewares = [
  68. {
  69. id: "Browsersync HTTP Protocol",
  70. route: require("../config").httpProtocol.path,
  71. handle: require("../http-protocol").middleware(bs)
  72. },
  73. {
  74. id: "Browsersync IE8 Support",
  75. route: "",
  76. handle: snippet.isOldIe(bs.options.get("excludedFileTypes").toJS())
  77. },
  78. {
  79. id: "Browsersync Response Modifier",
  80. route: "",
  81. handle: serverUtils.getSnippetMiddleware(bs)
  82. },
  83. {
  84. id: "Browsersync Client - versioned",
  85. route: bs.options.getIn(["scriptPaths", "versioned"]),
  86. handle: scripts
  87. },
  88. {
  89. id: "Browsersync Client",
  90. route: bs.options.getIn(["scriptPaths", "path"]),
  91. handle: scripts
  92. }
  93. ];
  94. /**
  95. * Add cors middleware to the front of the stack
  96. * if a user provided a 'cors' flag
  97. */
  98. if (bs.options.get("cors")) {
  99. defaultMiddlewares.unshift({
  100. id: "Browsersync CORS support",
  101. route: "",
  102. handle: serverUtils.getCorsMiddlewware()
  103. })
  104. }
  105. /**
  106. * Add serve static middleware
  107. */
  108. if (bs.options.get("serveStatic")) {
  109. var ssMiddlewares = serverUtils.getServeStaticMiddlewares(bs.options.get("serveStatic"), bs.options.get("serveStaticOptions", Immutable.Map({})).toJS());
  110. var withErrors = ssMiddlewares.filter(function(x) { return x.get("errors").size > 0 });
  111. var withoutErrors = ssMiddlewares.filter(function(x) { return x.get("errors").size === 0 });
  112. if (withErrors.size) {
  113. withErrors.forEach(function (item) {
  114. logger.logger.error("{red:Warning!} %s", item.getIn(["errors", 0, "data", "message"]));
  115. });
  116. }
  117. if (withoutErrors.size) {
  118. withoutErrors.forEach(function (item) {
  119. defaultMiddlewares.push.apply(defaultMiddlewares, item.get("items").toJS());
  120. });
  121. }
  122. }
  123. /**
  124. * Add user-provided middlewares
  125. */
  126. var userMiddlewares = bs.options.get("middleware").map(normaliseMiddleware).toArray();
  127. var beforeMiddlewares = userMiddlewares.filter(function (x) { return x.override; });
  128. var afterMiddlewares = userMiddlewares.filter(function (x) { return !x.override; });
  129. return [].concat(beforeMiddlewares, defaultMiddlewares, afterMiddlewares);
  130. function normaliseMiddleware(item) {
  131. /**
  132. * Object given in options, which
  133. * ended up being a Map
  134. */
  135. if (Map.isMap(item)) {
  136. return item.toJS();
  137. }
  138. /**
  139. * Single function
  140. */
  141. if (typeof item === "function") {
  142. return {
  143. route: "",
  144. handle: item
  145. }
  146. }
  147. /**
  148. * Plain obj
  149. */
  150. if ((item.route !== undefined) && item.handle) {
  151. return item;
  152. }
  153. }
  154. /**
  155. * Add the proxy Middleware to the end of the stack
  156. */
  157. },
  158. getBaseApp: function (bs) {
  159. var app = connect();
  160. var middlewares = serverUtils.getMiddlewares(bs);
  161. /**
  162. * Add all internal middlewares
  163. */
  164. middlewares.forEach(function (item) {
  165. app.stack.push(item);
  166. });
  167. return app;
  168. },
  169. getSnippetMiddleware: function (bs) {
  170. var rules = [];
  171. var blacklist = List([])
  172. .concat(bs.options.getIn(["snippetOptions", "ignorePaths"]))
  173. .concat(bs.options.getIn(["snippetOptions", "blacklist"]))
  174. .filter(Boolean);
  175. var whitelist = List([])
  176. .concat(bs.options.getIn(["snippetOptions", "whitelist"]));
  177. // Snippet
  178. rules.push(snippetUtils.getRegex(bs.options.get("snippet"), bs.options.get("snippetOptions")));
  179. // User
  180. bs.options.get("rewriteRules").forEach(function (rule) {
  181. if (Map.isMap(rule)) {
  182. rules.push(rule.toJS());
  183. }
  184. if (_.isPlainObject(rule)) {
  185. rules.push(rule);
  186. }
  187. });
  188. // Proxy
  189. if (bs.options.get("proxy")) {
  190. var proxyRule = require("./proxy-utils").rewriteLinks(bs.options.getIn(["proxy", "url"]).toJS());
  191. rules.push(proxyRule);
  192. }
  193. var lr = lrSnippet.create({
  194. rules: rules,
  195. blacklist: blacklist.toArray(),
  196. whitelist: whitelist.toArray()
  197. });
  198. return lr.middleware;
  199. },
  200. getCorsMiddlewware: function () {
  201. return function (req, res, next) {
  202. // Website you wish to allow to connect
  203. res.setHeader("Access-Control-Allow-Origin", "*");
  204. // Request methods you wish to allow
  205. res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
  206. // Request headers you wish to allow
  207. res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type");
  208. // Set to true if you need the website to include cookies in the requests sent
  209. // to the API (e.g. in case you use sessions)
  210. res.setHeader("Access-Control-Allow-Credentials", true);
  211. next();
  212. }
  213. },
  214. /**
  215. * @param ssOption
  216. * @param serveStaticOptions
  217. * @returns {*}
  218. */
  219. getServeStaticMiddlewares: function (ssOption, serveStaticOptions) {
  220. return ssOption.map(function (dir, i) {
  221. /**
  222. * When a user gives a plain string only, eg:
  223. * serveStatic: ['./temp']
  224. * ->
  225. * This means a middleware will be created with
  226. * route: ''
  227. * handle: serveStatic('./temp', options)
  228. */
  229. if (_.isString(dir)) {
  230. return getFromString(dir)
  231. }
  232. /**
  233. * If a user gave an object eg:
  234. * serveStatic: [{route: "", dir: ["test", "./tmp"]}]
  235. * ->
  236. * This means we need to create a middle for each route + dir combo
  237. */
  238. if (Immutable.Map.isMap(dir)) {
  239. return getFromMap(dir, i);
  240. }
  241. /**
  242. * At this point, an item in the serveStatic array was not a string
  243. * or an object so we return an error that can be logged
  244. */
  245. return fromJS({
  246. items: [],
  247. errors: [{
  248. type: "Invalid Type",
  249. data: {
  250. message: "Only strings and Objects (with route+dir) are supported for the ServeStatic option"
  251. }
  252. }]
  253. })
  254. });
  255. /**
  256. * @param {string} x
  257. * @returns {string}
  258. */
  259. function getRoute (x) {
  260. if (x === "") return "";
  261. return x[0] === "/" ? x : "/" + x;
  262. }
  263. /**
  264. * @param dir
  265. * @returns {Map}
  266. */
  267. function getFromString(dir) {
  268. return fromJS({
  269. items: [
  270. {
  271. route: "",
  272. handle: serveStatic(dir, serveStaticOptions)
  273. }
  274. ],
  275. errors: []
  276. })
  277. }
  278. /**
  279. * @param dir
  280. * @returns {Map}
  281. */
  282. function getFromMap(dir) {
  283. var ssOptions = (function () {
  284. if (dir.get("options")) {
  285. return dir.get("options").toJS();
  286. }
  287. return {}
  288. })();
  289. var route = Immutable.List([]).concat(dir.get("route")).filter(_.isString);
  290. var _dir = Immutable.List([]).concat(dir.get("dir")).filter(_.isString);
  291. if (_dir.size === 0) {
  292. return fromJS({
  293. items: [],
  294. errors: [{
  295. type: "Invalid Object",
  296. data: {
  297. message: "Serve Static requires a 'dir' property when using an Object"
  298. }
  299. }]
  300. })
  301. }
  302. var ssItems = (function () {
  303. /**
  304. * iterate over every 'route' item
  305. * @type {Immutable.List<any>|Immutable.List<*>|Immutable.List<any>|*}
  306. */
  307. var routeItems = (function () {
  308. /**
  309. * If no 'route' was given, assume we want to match all
  310. * paths
  311. */
  312. if (route.size === 0) {
  313. return _dir.map(function (dirString) {
  314. return Map({
  315. route: "",
  316. dir: dirString
  317. });
  318. });
  319. }
  320. return route.reduce(function (acc, routeString) {
  321. /**
  322. * For each 'route' item, also iterate through 'dirs'
  323. * @type {Immutable.Iterable<K, M>}
  324. */
  325. var perDir = _dir.map(function (dirString) {
  326. return Map({
  327. route: getRoute(routeString),
  328. dir: dirString
  329. })
  330. });
  331. return acc.concat(perDir);
  332. }, List([]));
  333. })();
  334. /**
  335. * Now create a serverStatic Middleware for each item
  336. */
  337. return routeItems.map(function (routeItem) {
  338. return routeItem.merge({
  339. handle: serveStatic(routeItem.get("dir"), ssOptions)
  340. });
  341. });
  342. })();
  343. return fromJS({
  344. items: ssItems,
  345. errors: []
  346. });
  347. }
  348. }
  349. };
  350. module.exports = serverUtils;