gina 0.1.1-alpha.99 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/LICENSE +1 -1
  2. package/README-4Contributors.md +30 -0
  3. package/README.md +125 -39
  4. package/bin/cli +130 -41
  5. package/bin/cli-debug +46 -15
  6. package/bin/cmd +63 -41
  7. package/bin/gina +57 -49
  8. package/framework/{v0.1.1-alpha.99/lib/inherits → v0.1.2-alpha.2}/LICENSE +1 -1
  9. package/framework/v0.1.2-alpha.2/VERSION +1 -0
  10. package/framework/{v0.1.1-alpha.99/core/asset/js/plugin/readme.md → v0.1.2-alpha.2/core/asset/plugin/README.md} +34 -12
  11. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/css/gina.min.css +1 -0
  12. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/css/gina.min.css.map +1 -0
  13. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/html/toolbar.html +251 -0
  14. package/framework/{v0.1.1-alpha.99/core/asset/js/plugin/dist → v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/js}/gina.js +4588 -3416
  15. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/js/gina.min.js +765 -0
  16. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/js/gina.min.js.map +8 -0
  17. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js +7 -0
  18. package/framework/v0.1.2-alpha.2/core/asset/plugin/dist/vendor/gina/js/gina.onload.min.js.map +8 -0
  19. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/config.js +315 -131
  20. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/index.js +460 -274
  21. package/framework/v0.1.2-alpha.2/core/connectors/couchbase/lib/connector.js +22 -0
  22. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/lib/connector.v2.js +51 -51
  23. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/lib/connector.v3.js +51 -51
  24. package/framework/v0.1.2-alpha.2/core/connectors/couchbase/lib/connector.v4.js +384 -0
  25. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/lib/n1ql.js +3 -2
  26. package/framework/v0.1.2-alpha.2/core/connectors/couchbase/lib/session-store.js +22 -0
  27. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/lib/session-store.v3.js +12 -12
  28. package/framework/v0.1.2-alpha.2/core/connectors/couchbase/lib/session-store.v4.js +361 -0
  29. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/controller/controller.js +1351 -902
  30. package/framework/v0.1.2-alpha.2/core/controller/index.js +23 -0
  31. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/dev/index.js +1 -1
  32. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/dev/lib/class.js +1 -1
  33. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/dev/lib/factory.js +2 -2
  34. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/gna.js +48 -24
  35. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/README.md +5 -0
  36. package/framework/v0.1.2-alpha.2/core/locales/dist/region/en.json +5727 -0
  37. package/framework/v0.1.2-alpha.2/core/locales/dist/region/fr.json +11452 -0
  38. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/index.js +2 -2
  39. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/src/make.js +39 -41
  40. package/framework/v0.1.2-alpha.2/core/locales/src/resources/region.mapping.json +43 -0
  41. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/model/entity.js +87 -67
  42. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/model/index.js +16 -16
  43. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/model/template/entityFactory.js +1 -1
  44. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/model/template/index.js +17 -15
  45. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/index.js +1 -1
  46. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/file/package.json +1 -1
  47. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/intl/package.json +1 -1
  48. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/intl/src/main.js +5 -5
  49. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/storage/package.json +1 -1
  50. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/storage/src/main.js +6 -5
  51. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/validator/package.json +1 -1
  52. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/validator/src/form-validator.js +404 -300
  53. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/validator/src/main.js +1384 -1314
  54. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/router.js +221 -122
  55. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/server.express.js +69 -65
  56. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/server.isaac.js +274 -180
  57. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/server.js +710 -615
  58. package/framework/v0.1.2-alpha.2/core/template/boilerplate/bundle/config/settings.json +12 -0
  59. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/config/settings.server.json +4 -4
  60. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/config/templates.json +4 -4
  61. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/controllers/controller.content.js +1 -1
  62. package/framework/v0.1.2-alpha.2/core/template/boilerplate/bundle/controllers/setup.js +111 -0
  63. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/index.js +13 -1
  64. package/framework/v0.1.2-alpha.2/core/template/boilerplate/bundle_templates/html/content/homepage.html +8 -0
  65. package/framework/v0.1.2-alpha.2/core/template/boilerplate/bundle_templates/html/includes/error-msg-noscript.html +11 -0
  66. package/framework/v0.1.2-alpha.2/core/template/boilerplate/bundle_templates/html/includes/error-msg-outdated-browser.html +8 -0
  67. package/framework/{v0.1.1-alpha.99/core/template/boilerplate/bundle_templates/html/layout → v0.1.2-alpha.2/core/template/boilerplate/bundle_templates/html/layouts}/main.html +10 -3
  68. package/framework/v0.1.2-alpha.2/core/template/command/gina.bat.tpl +8 -0
  69. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/command/gina.tpl +4 -4
  70. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/conf/env.json +12 -0
  71. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/conf/manifest.json +2 -0
  72. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/conf/package.json +2 -2
  73. package/framework/v0.1.2-alpha.2/core/template/conf/statics.json +12 -0
  74. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/conf/templates.json +9 -9
  75. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/console.js +3 -3
  76. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/context.js +233 -75
  77. package/framework/v0.1.2-alpha.2/helpers/data/LICENSE +9 -0
  78. package/framework/v0.1.2-alpha.2/helpers/data/README.md +12 -0
  79. package/framework/v0.1.2-alpha.2/helpers/data/package.json +20 -0
  80. package/framework/v0.1.2-alpha.2/helpers/data/src/main.js +295 -0
  81. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/dateFormat.js +9 -7
  82. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/index.js +13 -8
  83. package/framework/v0.1.2-alpha.2/helpers/json/LICENSE +9 -0
  84. package/framework/v0.1.2-alpha.2/helpers/json/README.md +12 -0
  85. package/framework/{v0.1.1-alpha.99/helpers/plugins → v0.1.2-alpha.2/helpers/json}/package.json +2 -2
  86. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/json/src/main.js +33 -28
  87. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/path.js +97 -22
  88. package/framework/{v0.1.1-alpha.99/helpers/json → v0.1.2-alpha.2/helpers/plugins}/package.json +2 -2
  89. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/plugins/src/api-error.js +23 -23
  90. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/plugins/src/main.js +3 -3
  91. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/prototypes.js +46 -38
  92. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/text.js +2 -2
  93. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/archiver/package.json +1 -1
  94. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/archiver/src/dep/jszip.min.js +3 -3
  95. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/archiver/src/main.js +183 -168
  96. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/aliases.json +4 -1
  97. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/add.js +84 -28
  98. package/framework/v0.1.2-alpha.2/lib/cmd/bundle/arguments.json +8 -0
  99. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/help.txt +4 -2
  100. package/framework/v0.1.2-alpha.2/lib/cmd/bundle/list.js +175 -0
  101. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/remove.js +39 -27
  102. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/restart.js +14 -8
  103. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/start.js +283 -49
  104. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/stop.js +93 -74
  105. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/add.js +87 -49
  106. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/list.js +26 -4
  107. package/framework/{v0.1.1-alpha.99/lib/cmd/scope → v0.1.2-alpha.2/lib/cmd/env}/remove.js +29 -24
  108. package/framework/v0.1.2-alpha.2/lib/cmd/env/use.js +106 -0
  109. package/framework/v0.1.2-alpha.2/lib/cmd/framework/build.js +93 -0
  110. package/framework/v0.1.2-alpha.2/lib/cmd/framework/init.js +932 -0
  111. package/framework/v0.1.2-alpha.2/lib/cmd/framework/link-node-modules.js +123 -0
  112. package/framework/v0.1.2-alpha.2/lib/cmd/framework/link.js +137 -0
  113. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/open.js +25 -1
  114. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/restart.js +78 -26
  115. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/set.js +120 -40
  116. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/start.js +49 -20
  117. package/framework/v0.1.2-alpha.2/lib/cmd/framework/status.js +144 -0
  118. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/stop.js +64 -31
  119. package/framework/v0.1.2-alpha.2/lib/cmd/framework/tail.js +303 -0
  120. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/version.js +19 -4
  121. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/helper.js +357 -53
  122. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/index.js +23 -23
  123. package/framework/v0.1.2-alpha.2/lib/cmd/port/inc/scan.js +142 -0
  124. package/framework/v0.1.2-alpha.2/lib/cmd/port/list.js +464 -0
  125. package/framework/v0.1.2-alpha.2/lib/cmd/port/reset.js +417 -0
  126. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/add.js +344 -157
  127. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/arguments.json +2 -1
  128. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/build.js +28 -28
  129. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/help.txt +7 -1
  130. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/list.js +22 -2
  131. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/remove.js +19 -17
  132. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/rename.js +11 -11
  133. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/protocol/set.js +260 -211
  134. package/framework/v0.1.2-alpha.2/lib/cmd/scope/add.js +129 -0
  135. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/scope/help.txt +4 -4
  136. package/framework/{v0.1.1-alpha.99/lib/cmd/env/use.js → v0.1.2-alpha.2/lib/cmd/scope/link-production.js} +22 -21
  137. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/scope/list.js +34 -11
  138. package/framework/v0.1.2-alpha.2/lib/cmd/scope/remove.js +122 -0
  139. package/framework/v0.1.2-alpha.2/lib/cmd/scope/use.js +68 -0
  140. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/view/add.js +35 -10
  141. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/collection/package.json +1 -1
  142. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/collection/src/main.js +247 -244
  143. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/config.js +33 -31
  144. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cron/package.json +1 -1
  145. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cron/src/main.js +16 -11
  146. package/framework/v0.1.2-alpha.2/lib/domain/LICENSE +9 -0
  147. package/framework/v0.1.2-alpha.2/lib/domain/README.md +46 -0
  148. package/framework/v0.1.2-alpha.2/lib/domain/dist/public_suffix_list.dat +14186 -0
  149. package/framework/v0.1.2-alpha.2/lib/domain/package.json +20 -0
  150. package/framework/v0.1.2-alpha.2/lib/domain/src/main.js +442 -0
  151. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/generator/index.js +5 -5
  152. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/index.js +3 -2
  153. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2/lib/inherits}/LICENSE +1 -1
  154. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/README.md +2 -2
  155. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/package.json +3 -4
  156. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/src/main.js +3 -3
  157. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/package.json +2 -2
  158. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/default/index.js +15 -2
  159. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/file/index.js +109 -14
  160. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/mq/index.js +12 -3
  161. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/mq/listener.js +29 -21
  162. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/mq/speaker.js +33 -4
  163. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/helper.js +22 -1
  164. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/main.js +36 -9
  165. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/math/index.js +9 -9
  166. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/README.md +2 -2
  167. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/package.json +1 -1
  168. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/src/main.js +118 -91
  169. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/model.js +10 -10
  170. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/proc.js +92 -49
  171. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/routing/package.json +1 -1
  172. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/routing/src/main.js +377 -420
  173. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/session-store.js +13 -7
  174. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/shell.js +3 -3
  175. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/swig-filters/package.json +1 -1
  176. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/swig-filters/src/main.js +140 -119
  177. package/framework/v0.1.2-alpha.2/lib/url/README.md +0 -0
  178. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/validator.js +2 -2
  179. package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/package.json +1 -1
  180. package/package.json +10 -10
  181. package/resources/home/main.json +39 -5
  182. package/resources/home/settings.json +8 -0
  183. package/resources/package.json.template +1 -1
  184. package/script/lib.js +0 -0
  185. package/script/post_install.js +179 -89
  186. package/script/pre_install.js +95 -12
  187. package/services/.gna/67fdf1b224a2ed5597e63d4b64283834468e05e3.txt +0 -0
  188. package/services/.gna/arch +1 -0
  189. package/services/.gna/locals.json +14 -0
  190. package/services/.gna/platform +1 -0
  191. package/services/configure +6 -0
  192. package/services/env.json +18 -0
  193. package/services/manifest.json +30 -0
  194. package/services/package.json +11 -0
  195. package/services/src/proxy/config/app.json +6 -0
  196. package/services/src/proxy/config/routing.json +11 -0
  197. package/services/src/proxy/config/settings.json +9 -0
  198. package/services/src/proxy/config/settings.server.json +31 -0
  199. package/services/src/proxy/config/statics.json +3 -0
  200. package/services/src/proxy/controllers/controller.content.js +58 -0
  201. package/services/src/proxy/controllers/controller.js +30 -0
  202. package/{framework/v0.1.1-alpha.99/core/template/boilerplate/bundle → services/src/proxy}/controllers/setup.js +14 -14
  203. package/services/src/proxy/index.js +31 -0
  204. package/services/src/proxy/lib/domain/README.md +48 -0
  205. package/services/src/proxy/lib/domain/src/config/public_suffix_list.dat +14186 -0
  206. package/services/src/toolbar/config/app.json +6 -0
  207. package/services/src/toolbar/config/routing.json +11 -0
  208. package/{framework/v0.1.1-alpha.99/core/template/boilerplate/bundle → services/src/toolbar}/config/settings.json +0 -0
  209. package/services/src/toolbar/config/settings.server.json +30 -0
  210. package/services/src/toolbar/controllers/controller.content.js +39 -0
  211. package/services/src/toolbar/controllers/controller.js +30 -0
  212. package/services/src/toolbar/controllers/setup.js +111 -0
  213. package/services/src/toolbar/index.js +43 -0
  214. package/utils/helper.js +25 -156
  215. package/utils/prototypes.js +9 -9
  216. package/utils/prototypes.json_clone.js +70 -37
  217. package/framework/v0.1.1-alpha.99/VERSION +0 -1
  218. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.js.map +0 -56
  219. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.min.css +0 -1
  220. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.min.css.map +0 -1
  221. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.min.js +0 -736
  222. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.min.js.map +0 -56
  223. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.onload.min.js +0 -5
  224. package/framework/v0.1.1-alpha.99/core/asset/js/plugin/dist/gina.onload.min.js.map +0 -8
  225. package/framework/v0.1.1-alpha.99/core/connectors/couchbase/lib/connector.js +0 -20
  226. package/framework/v0.1.1-alpha.99/core/connectors/couchbase/lib/session-store.js +0 -21
  227. package/framework/v0.1.1-alpha.99/core/controller/index.js +0 -27
  228. package/framework/v0.1.1-alpha.99/core/locales/dist/region/en.json +0 -9492
  229. package/framework/v0.1.1-alpha.99/core/locales/dist/region/fr.json +0 -9492
  230. package/framework/v0.1.1-alpha.99/core/locales/src/resources/region.mapping.json +0 -28
  231. package/framework/v0.1.1-alpha.99/core/template/boilerplate/bundle_templates/html/homepage.html +0 -4
  232. package/framework/v0.1.1-alpha.99/core/template/conf/statics.json +0 -10
  233. package/framework/v0.1.1-alpha.99/lib/cmd/bundle/arguments.json +0 -4
  234. package/framework/v0.1.1-alpha.99/lib/cmd/bundle/list.js +0 -129
  235. package/framework/v0.1.1-alpha.99/lib/cmd/env/remove.js +0 -150
  236. package/framework/v0.1.1-alpha.99/lib/cmd/framework/init.js +0 -541
  237. package/framework/v0.1.1-alpha.99/lib/cmd/framework/status.js +0 -72
  238. package/framework/v0.1.1-alpha.99/lib/cmd/framework/tail.js +0 -184
  239. package/framework/v0.1.1-alpha.99/lib/cmd/port/inc/scan.js +0 -108
  240. package/framework/v0.1.1-alpha.99/lib/cmd/port/list.js +0 -176
  241. package/framework/v0.1.1-alpha.99/lib/cmd/scope/set.js +0 -57
  242. package/framework/v0.1.1-alpha.99/lib/cmd/scope/unset.js +0 -44
  243. package/framework/v0.1.1-alpha.99/lib/cmd/scope/use.js +0 -79
  244. package/script/post_publish.js +0 -185
  245. package/script/prepare_version.js +0 -552
  246. /package/{framework/v0.1.1-alpha.99/core/template/command/gina.bat.tpl → bin/gina.bat} +0 -0
  247. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/AUTHORS +0 -0
  248. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/html/nolayout.html +0 -0
  249. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/html/static.html +0 -0
  250. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/android-chrome-192x192.png +0 -0
  251. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/android-chrome-512x512.png +0 -0
  252. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/apple-touch-icon.png +0 -0
  253. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/favicon-16x16.png +0 -0
  254. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/favicon-32x32.png +0 -0
  255. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/asset/img/favicon.ico +0 -0
  256. /package/framework/{v0.1.1-alpha.99/core/asset/js → v0.1.2-alpha.2/core/asset}/plugin/uuid.json +0 -0
  257. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/connectors/couchbase/lib/session-store.v2.js +0 -0
  258. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/controller/controller.framework.js +0 -0
  259. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/.travis.yml +0 -0
  260. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/LICENSE +0 -0
  261. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/README.md +0 -0
  262. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/deps/encoding/encoding-indexes.js +0 -0
  263. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/deps/encoding/encoding.js +0 -0
  264. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/lib/main.js +0 -0
  265. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/lib/types/multipart.js +0 -0
  266. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/lib/types/urlencoded.js +0 -0
  267. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/lib/utils.js +0 -0
  268. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/busboy/package.json +0 -0
  269. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/deps/swig-client/swig-2.0.0.min.js +0 -0
  270. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/dev/lib/tools.js +0 -0
  271. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/currency.json +0 -0
  272. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/dist/language/en.json +0 -0
  273. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/dist/language/fr.json +0 -0
  274. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/src/resources/currency.csv +0 -0
  275. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/locales/src/resources/region.csv +0 -0
  276. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/mime.types +0 -0
  277. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/README.md +0 -0
  278. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/file/README.md +0 -0
  279. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/file/build.json +0 -0
  280. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/intl/README.md +0 -0
  281. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/intl/build.json +0 -0
  282. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/storage/README.md +0 -0
  283. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/storage/build.json +0 -0
  284. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/validator/README.md +0 -0
  285. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/plugins/lib/validator/build.json +0 -0
  286. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/status.codes +0 -0
  287. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/config/app.json +0 -0
  288. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/config/routing.json +0 -0
  289. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle/controllers/controller.js +0 -0
  290. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_namespace/controllers/controller.js +0 -0
  291. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_public/css/default.css +0 -0
  292. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_public/css/vendor/readme.md +0 -0
  293. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_public/favicon.ico +0 -0
  294. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_public/js/vendor/readme.md +0 -0
  295. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_public/readme.md +0 -0
  296. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/boilerplate/bundle_templates/handlers/main.js +0 -0
  297. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/conf/settings.json +0 -0
  298. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/client/json/401.json +0 -0
  299. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/client/json/403.json +0 -0
  300. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/client/json/404.json +0 -0
  301. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/server/html/50x.html +0 -0
  302. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/server/json/500.json +0 -0
  303. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/error/server/json/503.json +0 -0
  304. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/core/template/extensions/logger/config.json +0 -0
  305. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/plugins/README.md +0 -0
  306. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/helpers/task.js +0 -0
  307. /package/framework/{v0.1.1-alpha.99/helpers/json → v0.1.2-alpha.2/lib/archiver}/README.md +0 -0
  308. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/archiver/build.json +0 -0
  309. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/copy.js +0 -0
  310. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/cp.js +0 -0
  311. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/help.js +0 -0
  312. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/rename.js +0 -0
  313. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/rm.js +0 -0
  314. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/bundle/status.js +0 -0
  315. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/get.js +0 -0
  316. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/help.js +0 -0
  317. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/help.txt +0 -0
  318. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/link-dev.js +0 -0
  319. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/rm.js +0 -0
  320. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/set.js +0 -0
  321. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/env/unset.js +0 -0
  322. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/dot.js +0 -0
  323. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/get.js +0 -0
  324. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/help.js +0 -0
  325. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/help.txt +0 -0
  326. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/msg.json +0 -0
  327. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/framework/update.js +0 -0
  328. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/gina-dev.1.md +0 -0
  329. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/gina-framework.1.md +0 -0
  330. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/gina.1.md +0 -0
  331. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/msg.json +0 -0
  332. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/port/help.js +0 -0
  333. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/port/help.txt +0 -0
  334. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/port/set.js +0 -0
  335. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/help.js +0 -0
  336. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/import.js +0 -0
  337. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/move.js +0 -0
  338. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/restart.js +0 -0
  339. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/rm.js +0 -0
  340. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/start.js +0 -0
  341. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/status.js +0 -0
  342. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/project/stop.js +0 -0
  343. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/protocol/help.js +0 -0
  344. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/protocol/help.txt +0 -0
  345. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/protocol/list.js +0 -0
  346. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/scope/help.js +0 -0
  347. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/scope/link-local.js +0 -0
  348. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cmd/scope/rm.js +0 -0
  349. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/collection/README.md +0 -0
  350. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/collection/build.json +0 -0
  351. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/cron/README.md +0 -0
  352. /package/framework/{v0.1.1-alpha.99/lib/archiver/README.md → v0.1.2-alpha.2/lib/domain/exemples/backend.js} +0 -0
  353. /package/framework/{v0.1.1-alpha.99/lib/routing/README.md → v0.1.2-alpha.2/lib/domain/exemples/frontend.html} +0 -0
  354. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/example/inheriting_eventemitter.js +0 -0
  355. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/example/protected_inheritance.js +0 -0
  356. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/example/simple_inheritance.js +0 -0
  357. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/inherits/example/super_attribute_overridden_by_child_on_init.js +0 -0
  358. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/README.md +0 -0
  359. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/file/lib/logrotator/README.md +0 -0
  360. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/logger/src/containers/file/lib/logrotator/index.js +0 -0
  361. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/example/merge.js +0 -0
  362. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/example/merge_2_literal objects.js +0 -0
  363. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/merge/example/merge_and_preserve_first.js +0 -0
  364. /package/framework/{v0.1.1-alpha.99/lib/swig-filters → v0.1.2-alpha.2/lib/routing}/README.md +0 -0
  365. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/routing/build.json +0 -0
  366. /package/framework/{v0.1.1-alpha.99/lib/url → v0.1.2-alpha.2/lib/swig-filters}/README.md +0 -0
  367. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/url/index.js +0 -0
  368. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/url/mocks.json +0 -0
  369. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/url/routing.json +0 -0
  370. /package/framework/{v0.1.1-alpha.99 → v0.1.2-alpha.2}/lib/url/test.js +0 -0
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /*
3
3
  * This file is part of the gina package.
4
- * Copyright (c) 2009-2022 Rhinostone <contact@gina.io>
4
+ * Copyright (c) 2009-2023 Rhinostone <contact@gina.io>
5
5
  *
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
@@ -19,13 +19,15 @@ var zlib = require('zlib');
19
19
  // var tls = require('tls');
20
20
  // var crypto = require('crypto');
21
21
 
22
- var lib = require('./../../lib') || require.cache[require.resolve('./../../lib')];
22
+ var lib = require('./../../lib') || require.cache[require.resolve('./../../lib')];
23
23
  var merge = lib.merge;
24
24
  var inherits = lib.inherits;
25
25
  var console = lib.logger;
26
26
  var Collection = lib.Collection;
27
- var routingUtils = lib.routing;
27
+ var routingLib = lib.routing;
28
28
  var swig = require('swig');
29
+ // Swig 2
30
+ // var swig = require('./../deps/swig-client/swig-2.0.0.min.js');
29
31
  var SwigFilters = lib.SwigFilters;
30
32
  var statusCodes = requireJSON( _( getPath('gina').core + '/status.codes') );
31
33
 
@@ -44,9 +46,9 @@ function SuperController(options) {
44
46
 
45
47
  //public
46
48
  this.name = 'SuperController';
47
- this.engine = {};
48
-
49
-
49
+ this.engine = {};
50
+
51
+
50
52
  var self = this;
51
53
  //private
52
54
  var local = {
@@ -68,16 +70,16 @@ function SuperController(options) {
68
70
  if ( typeof(SuperController.initialized) != 'undefined' ) {
69
71
  return getInstance()
70
72
  } else {
71
-
73
+
72
74
  SuperController.instance = self;
73
-
74
-
75
+
76
+
75
77
  if (local.options) {
76
78
  SuperController.instance._options = local.options;
77
79
  }
78
-
80
+
79
81
  SuperController.initialized = true;
80
-
82
+
81
83
  }
82
84
  }
83
85
 
@@ -85,46 +87,91 @@ function SuperController(options) {
85
87
  local.options = SuperController.instance._options = options;
86
88
  // 2022-03-07 Fix for none-developpement environnements (without cache)
87
89
  self._options = local.options;
88
-
90
+
89
91
  return SuperController.instance;
90
92
  }
91
93
 
92
94
  var hasViews = function() {
93
95
  return ( typeof(local.options.template) != 'undefined' ) ? true : false;
94
96
  }
95
-
97
+
96
98
  /**
97
99
  * isHttp2
98
100
  * Returns `true` if server configured for HTTP/2
99
- *
101
+ *
100
102
  * @returns {boolean} isHttp2
101
103
  */
102
104
  var isHttp2 = function() {
103
- var options = local.options;
105
+ var options = local.options;
104
106
  var protocolVersion = ~~options.conf.server.protocol.match(/\/(.*)$/)[1].replace(/\.\d+/, '');
105
107
  var httpLib = options.conf.server.protocol.match(/^(.*)\//)[1] + ( (protocolVersion >= 2) ? protocolVersion : '' );
106
-
107
-
108
+
109
+
108
110
  return /http2/.test(httpLib)
109
111
  }
112
+
113
+ var headersSent = function(res) {
114
+ var _res = ( typeof(res) != 'undefined' ) ? res : local.res;
115
+
116
+ if ( typeof(_res.headersSent) != 'undefined' ) {
117
+ return _res.headersSent
118
+ }
119
+
120
+ if (
121
+ typeof(_res.stream) != 'undefined'
122
+ && typeof(_res.stream.headersSent) != 'undefined'
123
+ && _res.stream.headersSent != 'null'
124
+ ) {
125
+ return true
126
+ }
127
+
128
+ return false;
129
+ }
110
130
  /**
111
131
  * isSecured
112
132
  * Returns `true` if server configured to handle a HTTPS exchanges
113
- *
133
+ *
114
134
  * @returns {boolean} isSecured
115
135
  */
116
136
  var isSecured = function() {
117
137
  return /https/.test(local.options.conf.server.scheme)
118
138
  }
119
-
139
+
140
+ /**
141
+ * freeMemory
142
+ *
143
+ * @param {array} variables
144
+ * @param {boolean} isGlobalModeNeeded
145
+ */
146
+ var freeMemory = function(variables, isGlobalModeNeeded) {
147
+ if ( !Array.isArray(variables) || !variables.length ) {
148
+ return;
149
+ }
150
+ if ( typeof(isGlobalModeNeeded) == 'undefined' ) {
151
+ isGlobalModeNeeded = true;
152
+ }
153
+ var i = 0, len = variables.length;
154
+ while (i<len) {
155
+ if ( typeof(variables[i]) != 'undefined' ) {
156
+ variables[i] = null;
157
+ }
158
+ ++i;
159
+ }
160
+
161
+ if (/^true$/i.test(isGlobalModeNeeded) ) {
162
+ // all but local.options becasue of `self.requireController('namespace', self._options)` calls
163
+ // local = null;
164
+ }
165
+ }
166
+
120
167
  this.getRequestObject = function() {
121
168
  return local.req;
122
169
  }
123
-
170
+
124
171
  this.getResponseObject = function() {
125
172
  return local.res;
126
173
  }
127
-
174
+
128
175
  this.getNextCallback = function() {
129
176
  return local.next;
130
177
  }
@@ -141,12 +188,18 @@ function SuperController(options) {
141
188
  this.isLocalScope = function() {
142
189
  return (/^true$/i.test(process.env.NODE_SCOPE_IS_LOCAL)) ? true : false;
143
190
  }
191
+ /**
192
+ * Check if the project scope is set for production
193
+ * */
194
+ this.isProductionScope = function() {
195
+ return (/^true$/i.test(process.env.NODE_SCOPE_IS_PRODUCTION)) ? true : false;
196
+ }
144
197
 
145
198
  this.setOptions = function(req, res, next, options) {
146
199
  local.options = SuperController.instance._options = options;
147
200
  local.options.renderingStack = (local.options.renderingStack) ? local.options.renderingStack : [];
148
201
  local.options.isRenderingCustomError = (local.options.isRenderingCustomError) ? local.options.isRenderingCustomError : false;
149
-
202
+
150
203
 
151
204
  // N.B.: Avoid setting `page` properties as much as possible from the routing.json
152
205
  // It will be easier for the framework if set from the controller.
@@ -169,36 +222,39 @@ function SuperController(options) {
169
222
  // var data = { page: { view: { title: "My Title"}}};
170
223
  // self.render(data)
171
224
  // }
172
-
225
+
173
226
  if ( typeof(options.conf.content.routing[options.rule].param) != 'undefined' ) {
174
227
  var str = 'page.'
175
228
  , p = options.conf.content.routing[options.rule].param
176
229
  ;
177
-
178
- for (var key in p) {
230
+
231
+ for (let key in p) {
179
232
  if ( p.hasOwnProperty(key) && !/^(control)$/.test(key) ) {
180
233
  str += key + '.';
181
- var obj = p[key], value = '';
182
- for (var prop in obj) {
234
+ let obj = p[key], value = '';
235
+ for (let prop in obj) {
183
236
  if (obj.hasOwnProperty(prop)) {
184
- value += obj[prop]
237
+ value += obj[prop];
238
+ continue;
239
+ }
240
+
241
+ if ( /^:/.test(value) ) {
242
+ str = 'page.view.params.'+ key + '.';
243
+ set(str.substr(0, str.length-1), req.params[value.substr(1)]);
244
+ } else if (/^(file|title)$/.test(key)) {
245
+ str = 'page.view.'+ key + '.';
246
+ set(str.substr(0, str.length-1), value);
185
247
  } else {
248
+ set(str.substr(0, str.length-1), value)
249
+ }
186
250
 
187
- if ( /^:/.test(value) ) {
188
- str = 'page.view.params.'+ key + '.';
189
- set(str.substr(0, str.length-1), req.params[value.substr(1)]);
190
- } else if (/^(file|title)$/.test(key)) {
191
- str = 'page.view.'+ key + '.';
192
- set(str.substr(0, str.length-1), value);
193
- } else {
194
- set(str.substr(0, str.length-1), value)
195
- }
251
+ str = 'page.'
196
252
 
197
- str = 'page.'
198
- }
199
253
  }
200
254
  }
201
255
  }
256
+
257
+ freeMemory([str, p], false);
202
258
  }
203
259
 
204
260
  local.req = req;
@@ -206,30 +262,34 @@ function SuperController(options) {
206
262
  local.next = next;
207
263
 
208
264
  getParams(req);
209
- if ( typeof(local.options.template) != 'undefined' && typeof(local.options.control) != 'undefined' ) {
210
-
211
-
265
+ if (
266
+ typeof(local.options.template) != 'undefined'
267
+ && typeof(local.options.control) != 'undefined'
268
+ ) {
212
269
  var action = local.options.control
213
270
  , rule = local.options.rule
214
271
  , ext = 'html' // by default
215
272
  , isWithoutLayout = false // by default
216
- , namespace = local.options.namespace || '';
217
-
273
+ , namespace = local.options.namespace || ''
274
+ ;
218
275
 
219
- if ( typeof(local.options.template) != 'undefined' && local.options.template ) {
220
- if (
221
- typeof(local.options.template.ext) != 'undefined'
222
- && local.options.template.ext
276
+ if (
277
+ typeof(local.options.template) != 'undefined'
278
+ && local.options.template
279
+ ) {
280
+ if (
281
+ typeof(local.options.template.ext) != 'undefined'
282
+ && local.options.template.ext
223
283
  && local.options.template.ext != ''
224
284
  ) {
225
285
  ext = local.options.template.ext
226
286
  }
227
-
287
+
228
288
  if ( !/\./.test(ext) ) {
229
289
  ext = '.' + ext;
230
290
  local.options.template.ext = ext
231
291
  }
232
-
292
+
233
293
  if (
234
294
  typeof(local.options.template.layout) == 'undefined'
235
295
  || /^false$/.test(local.options.template.layout)
@@ -238,27 +298,27 @@ function SuperController(options) {
238
298
  isWithoutLayout = true;
239
299
  }
240
300
  }
241
-
242
-
301
+
302
+
243
303
  if ( hasViews() ) {
244
304
 
245
305
  if ( typeof(local.options.file) == 'undefined') {
246
306
  local.options.file = 'index'
247
307
  }
248
-
308
+
249
309
  if ( typeof(local.options.isWithoutLayout) == 'undefined' || !isWithoutLayout ) {
250
310
  local.options.isWithoutLayout = false;
251
311
  }
252
-
312
+
253
313
  rule = local.options.rule;
254
- namespace = local.options.namespace || 'default';
255
-
256
-
314
+ namespace = local.options.namespace || 'default';
315
+
316
+
257
317
  set('page.view.file', local.options.file);
258
318
  set('page.view.title', rule.replace(new RegExp('@' + options.conf.bundle), ''));
259
319
  set('page.view.namespace', namespace);
260
- }
261
-
320
+ }
321
+
262
322
 
263
323
  var ctx = getContext('gina');
264
324
  // new declaration && overrides
@@ -270,26 +330,32 @@ function SuperController(options) {
270
330
  "middleware" : ctx.middleware
271
331
  };
272
332
 
333
+ set('page.environment.allocated memory', (require('v8').getHeapStatistics().heap_size_limit / (1024 * 1024 * 1024)).toFixed(2) +' GB');
334
+
273
335
  set('page.environment.gina', version.number);
274
336
  set('page.environment.gina pid', GINA_PID);
275
337
  set('page.environment.nodejs', version.nodejs +' '+ version.platform +' '+ version.arch);
276
338
  set('page.environment.engine', options.conf.server.engine);//version.middleware
277
339
  set('page.environment.env', process.env.NODE_ENV);
278
340
  set('page.environment.envIsDev', self.isCacheless());
341
+ set('page.environment.scope', process.env.NODE_SCOPE);
342
+ set('page.environment.scopeIsLocal', /^true$/i.test(process.env.NODE_SCOPE_IS_LOCAL) );
343
+ set('page.environment.scopeIsProduction', /^true$/i.test(process.env.NODE_SCOPE_IS_PRODUCTION) );
279
344
  set('page.environment.date.now', new Date().format("isoDateTime"));
280
-
281
-
345
+
346
+
282
347
  var routing = local.options.conf.routing = ctx.config.envConf.routing; // all routes
283
- set('page.environment.routing', escape(JSON.stringify(routing))); // export for GFF
348
+ set('page.environment.routing', encodeRFC5987ValueChars(JSON.stringify(routing))); // export for GFF
284
349
  //reverseRouting
285
350
  var reverseRouting = local.options.conf.reverseRouting = ctx.config.envConf.reverseRouting; // all routes
286
- set('page.environment.reverseRouting', escape(JSON.stringify(reverseRouting))); // export for GFF
287
-
351
+ set('page.environment.reverseRouting', encodeRFC5987ValueChars(JSON.stringify(reverseRouting))); // export for GFF
352
+
288
353
  var forms = local.options.conf.forms = options.conf.content.forms // all forms
289
- set('page.environment.forms', escape(JSON.stringify(forms))); // export for GFF
354
+ set('page.environment.forms', encodeRFC5987ValueChars(JSON.stringify(forms))); // export for GFF
290
355
  set('page.forms', options.conf.content.forms);
291
-
356
+
292
357
  set('page.environment.hostname', ctx.config.envConf[options.conf.bundle][process.env.NODE_ENV].hostname);
358
+ set('page.environment.rootDomain', ctx.config.envConf[options.conf.bundle][process.env.NODE_ENV].rootDomain);
293
359
  set('page.environment.webroot', options.conf.server.webroot);
294
360
  set('page.environment.bundle', options.conf.bundle);
295
361
  set('page.environment.project', options.conf.projectName);
@@ -298,14 +364,14 @@ function SuperController(options) {
298
364
  set('page.environment.port', options.conf.server.port);
299
365
  set('page.environment.debugPort', options.conf.server.debugPort);
300
366
  set('page.environment.pid', process.pid);
301
-
302
-
367
+
368
+
303
369
  set('page.view.ext', ext);
304
370
  set('page.view.control', action);
305
371
  set('page.view.controller', local.options.controller.replace(options.conf.bundlesPath, ''), true);
306
372
  if (typeof (local.options.controlRequired) != 'undefined' ) {
307
373
  set('page.view.controlRequired', local.options.controlRequired);
308
- }
374
+ }
309
375
  set('page.view.method', local.options.method);
310
376
  set('page.view.namespace', namespace); // by default
311
377
  set('page.view.url', req.url);
@@ -314,12 +380,12 @@ function SuperController(options) {
314
380
  set('page.view.html.properties.mode.javascriptsDeferEnabled', local.options.template.javascriptsDeferEnabled);
315
381
  set('page.view.html.properties.mode.routeNameAsFilenameEnabled', local.options.template.routeNameAsFilenameEnabled);
316
382
  }
317
-
318
-
383
+
384
+
319
385
  var parameters = JSON.clone(req.getParams());
320
386
  parameters = merge(parameters, options.conf.content.routing[rule].param);
321
387
  // excluding default page properties
322
- delete parameters[0];
388
+ delete parameters[0];
323
389
  delete parameters.file;
324
390
  delete parameters.control;
325
391
  delete parameters.title;
@@ -329,7 +395,7 @@ function SuperController(options) {
329
395
 
330
396
  set('page.view.route', rule);
331
397
 
332
-
398
+
333
399
  var acceptLanguage = GINA_CULTURE; // by default : language-COUNTRY
334
400
  if ( typeof(req.headers['accept-language']) != 'undefined' ) {
335
401
  acceptLanguage = req.headers['accept-language']
@@ -348,8 +414,8 @@ function SuperController(options) {
348
414
 
349
415
  try {
350
416
  userLocales = locales.findOne({ lang: userLangCode }).content;
351
- } catch (err) {
352
- //var defaultRegion = (local.options.conf.content.settings.region) ? local.options.conf.content.settings.region.shortCode
417
+ } catch (err) {
418
+ //var defaultRegion = (local.options.conf.content.settings.region) ? local.options.conf.content.settings.region.shortCode
353
419
  console.warn('language code `'+ userLangCode +'` not handled by current locales setup: replacing by default: `'+ local.options.conf.content.settings.region.shortCode +'`');
354
420
  userLocales = locales.findOne({ lang: local.options.conf.content.settings.region.shortCode }).content // by default
355
421
  }
@@ -359,7 +425,7 @@ function SuperController(options) {
359
425
 
360
426
  // user locale
361
427
  options.conf.locale = new Collection(userLocales).findOne({ short: userCountryCode }) || {};
362
-
428
+
363
429
  //set('page.date.now', new Date().format("isoDateTime"));
364
430
  if ( typeof(options.conf.locale) == 'undefined' || !options.conf.locale ) {
365
431
  options.conf.locale = {}
@@ -370,21 +436,22 @@ function SuperController(options) {
370
436
  set('page.view.locale', options.conf.locale);
371
437
  set('page.view.lang', userCulture);
372
438
  }
373
-
439
+
374
440
  if ( !getContext('isProxyHost') ) {
375
441
  var isProxyHost = ( typeof(req.headers.host) != 'undefined' && local.options.conf.server.scheme +'://'+ req.headers.host != local.options.conf.hostname || typeof(req.headers[':authority']) != 'undefined' && local.options.conf.server.scheme +'://'+ req.headers[':authority'] != local.options.conf.hostname ) ? true : false;
376
442
  setContext('isProxyHost', isProxyHost);
443
+ isProxyHost = null;
377
444
  }
378
-
445
+
379
446
  //TODO - detect when to use swig
380
447
  var dir = null;
381
448
  if (local.options.template || self.templates) {
382
449
  dir = local.options.template.templates || self.templates;
383
-
450
+
384
451
  var swigOptions = {
385
452
  autoescape : ( typeof(local.options.autoescape) != 'undefined') ? local.options.autoescape : false,
386
453
  // `memory` is no working yet ... advanced rendering setup required
387
- //cache : (local.options.cacheless) ? false : 'memory'
454
+ // cache : (local.options.cacheless) ? false : 'memory'
388
455
  cache : false
389
456
  };
390
457
  if (dir) {
@@ -394,18 +461,25 @@ function SuperController(options) {
394
461
  local._swigOptions = JSON.clone(swigOptions);
395
462
  }
396
463
  swig.setDefaults(swigOptions);
397
- // used for self.engine.compile(tpl, swigOptions)(data)
464
+ // used for self.engine.compile(tpl, swigOptions)(swigData)
398
465
  swig.getOptions = function() {
399
466
  return local._swigOptions;
400
467
  }
401
468
  // preserve the same timezone as the system
402
469
  var defaultTZOffset = new Date().getTimezoneOffset();
403
470
  swig.setDefaultTZOffset(defaultTZOffset);
404
-
471
+ defaultTZOffset = null;
472
+
405
473
  self.engine = swig;
474
+
475
+ dir = null;
476
+ swigOptions = null;
477
+
406
478
  }
479
+
480
+ freeMemory([action, rule, ext, isWithoutLayout, namespace, ctx, version, routing, reverseRouting, forms, parameters, acceptLanguage, userCulture, userCultureCode, userLangCode, userCountryCode, locales, userLocales], false);
407
481
  }
408
-
482
+
409
483
  this.renderWithoutLayout = function (data, displayToolbar) {
410
484
 
411
485
  // preventing multiple call of self.renderWithoutLayout() when controller is rendering from another required controller
@@ -414,7 +488,7 @@ function SuperController(options) {
414
488
  }
415
489
 
416
490
  local.options.isWithoutLayout = true;
417
-
491
+
418
492
  self.render(data, displayToolbar);
419
493
  }
420
494
 
@@ -444,47 +518,188 @@ function SuperController(options) {
444
518
  ) ? true : false;
445
519
  if (isRenderingCustomError)
446
520
  delete userData.isRenderingCustomError;
447
-
521
+
448
522
  var localOptions = (errOptions) ? errOptions : local.options;
449
523
  localOptions.renderingStack.push( self.name );
450
524
  // preventing multiple call of self.render() when controller is rendering from another required controller
451
525
  if ( localOptions.renderingStack.length > 1 && !isRenderingCustomError ) {
452
- return false
526
+ return false;
453
527
  }
454
-
455
-
528
+
529
+
456
530
  var data = null
457
531
  , layout = null
458
532
  , template = null
459
533
  , file = null
460
534
  , path = null
461
535
  , plugin = null
462
- , isWithoutLayout = (localOptions.isWithoutLayout) ? true : false
536
+ // By default
537
+ , isWithoutLayout = (localOptions.isWithoutLayout) ? true : false
463
538
  ;
464
-
539
+
540
+ try {
541
+ data = getData();
542
+ // Display session
543
+ if (
544
+ typeof(local.req.session) != 'undefined'
545
+ ) {
546
+ if ( typeof(data.page.data) == 'undefined' ) {
547
+ data.page.data = {};
548
+ }
549
+
550
+ if ( typeof(local.req.session.cookie._expires) != 'undefined' ) {
551
+ var dateEnd = local.req.session.cookie._expires;
552
+ var dateStart = ( typeof(local.req.session.lastModified) != 'undefined')
553
+ ? new Date(local.req.session.lastModified)
554
+ : new Date()
555
+ ;
556
+ var elapsed = dateEnd - dateStart;
557
+ // var expiresAt =
558
+ if ( typeof(data.page.data.session) == 'undefined' ) {
559
+ data.page.data.session = {
560
+ id : local.req.session.id,
561
+ lastModified: local.req.session.lastModified
562
+ };
563
+ }
564
+ // In milliseconds
565
+ data.page.data.session.createdAt = local.req.session.createdAt;
566
+ data.page.data.session.expiresAt = dateEnd.format('isoDateTime');
567
+ data.page.data.session.timeout = elapsed;
568
+
569
+ dateEnd = null;
570
+ dateStart = null;
571
+ elapsed = null;
572
+ }
573
+ }
574
+
575
+ // in case `local.req.routing.param.file` has been changed on the fly
576
+ if (
577
+ local.req.routing.param.file
578
+ && local.req.routing.param.file != data.page.view.file
579
+ ) {
580
+ data.page.view.file = local.req.routing.param.file;
581
+ }
582
+ if (
583
+ local.req.routing.param.ext
584
+ && local.req.routing.param.ext != data.page.view.ext
585
+ ) {
586
+ data.page.view.ext = local.req.routing.param.ext;
587
+ }
588
+ file = (isRenderingCustomError) ? localOptions.file : data.page.view.file;
589
+ // making path thru [namespace &] file
590
+ if ( typeof(localOptions.namespace) != 'undefined' && localOptions.namespace ) {
591
+ // excepted for custom paths
592
+ var fileNamingConvention = file.replace(localOptions.namespace+'-', '');
593
+ if ( !/^(\.|\/|\\)/.test(file) && file != fileNamingConvention ) {
594
+ var _ext = data.page.view.ext;
595
+
596
+ console.warn('file `'+ file +'` used in routing `'+ localOptions.rule +'` does not respect gina naming convention ! You should rename the file `'+ file + _ext +'` to `'+ ''+ fileNamingConvention + _ext +'`');
597
+ console.warn('The reason you are getting this message is because your filename begeins with `<namespace>-`\n If you don\‘t want to rename, use template path like ./../'+ localOptions.namespace +'/'+file);
598
+ file = ''+ file.replace(localOptions.namespace+'-', '');
599
+ }
600
+ fileNamingConvention = null;
601
+ _ext = null;
602
+
603
+
604
+ // means that rule name === namespace -> pointing to root namespace dir
605
+ if (!file || file === localOptions.namespace) {
606
+ file = 'index'
607
+ }
608
+ path = (isRenderingCustomError) ? _(file) : _(localOptions.template.html +'/'+ localOptions.namespace + '/' + file)
609
+ } else {
610
+ if ( localOptions.path && !/(\?|\#)/.test(localOptions.path) ) {
611
+ path = _(localOptions.path);
612
+ var re = new RegExp( data.page.view.ext+'$');
613
+ if ( data.page.view.ext && re.test(data.page.view.file) ) {
614
+ data.page.view.path = path.replace('/'+ data.page.view.file, '');
615
+
616
+ path = path.replace(re, '');
617
+ data.page.view.file = data.page.view.file.replace(re, '');
618
+
619
+ } else {
620
+ data.page.view.path = path.replace('/'+ data.page.view.file, '');
621
+ }
622
+ re = null;
623
+ } else {
624
+ path = (!isRenderingCustomError && !/^(\.|\/|\\)/.test(file))
625
+ ? _(localOptions.template.html +'/'+ file)
626
+ : file
627
+ }
628
+ }
629
+
630
+ if (data.page.view.ext && !new RegExp(data.page.view.ext+ '$').test(file) ) {
631
+ path += data.page.view.ext
632
+ }
633
+
634
+ data.page.view.path = path;
635
+ } catch (dataErr) {
636
+ return self.throwError(dataErr);
637
+ }
638
+
639
+ // isWithoutLayout from content
640
+ var pageContentObj = new _(data.page.view.path);
641
+ var _templateContent = fs.readFileSync(path).toString() || null;
642
+ var hasLayoutInPath = /\{\%(\s+extends|extends)/.test(_templateContent) || false;
643
+ var layoutPath = null;
644
+
645
+ if (
646
+ !isWithoutLayout
647
+ && !isRenderingCustomError
648
+ && pageContentObj.existsSync()
649
+ && !hasLayoutInPath
650
+ ) {
651
+ isWithoutLayout = true;
652
+ }
653
+ pageContentObj = null;
654
+
655
+ // Retrieve layoutPath from content
656
+ if (hasLayoutInPath && _templateContent) {
657
+ var extendFound = _templateContent.match(/\{\%(\s+extends|extends)(.*)\%}/);
658
+ if (extendFound && Array.isArray(extendFound)) {
659
+ var extendPath = null;
660
+ try {
661
+ // localOptions.template.templates +'/'+
662
+ layoutPath = extendFound[0].match(/(\"|\')(.*)(\"|\')/)[0].replace(/(\"|\')/g, '');
663
+ data.page.view.layout = layoutPath;
664
+ layoutPath = localOptions.template.templates +'/'+ layoutPath;
665
+ localOptions.template.layout = layoutPath;
666
+ } catch (extendErr) {
667
+ // nothing to do
668
+ }
669
+ extendPath = null;
670
+ }
671
+ extendFound = null;
672
+ }
673
+ hasLayoutInPath = null;
674
+ _templateContent = null;
675
+
465
676
  localOptions.debugMode = ( typeof(displayToolbar) == 'undefined' ) ? undefined : ( (/true/i.test(displayToolbar)) ? true : false ); // only active for dev env
466
-
677
+
467
678
  // specific override
468
679
  if (
469
680
  self.isCacheless()
470
- && typeof(local.req[ local.req.method.toLowerCase() ]) != 'undefined'
471
- && typeof(local.req[ local.req.method.toLowerCase() ].debug) != 'undefined'
681
+ && typeof(local.req[ local.req.method.toLowerCase() ]) != 'undefined'
682
+ && typeof(local.req[ local.req.method.toLowerCase() ].debug) != 'undefined'
472
683
  ) {
473
- localOptions.debugMode = ( /true/i.test(local.req[ local.req.method.toLowerCase() ].debug) ) ? true : false;
474
- } else if (
475
- self.isCacheless()
684
+ if ( !/^(true|false)$/i.test(local.req[ local.req.method.toLowerCase() ].debug) ) {
685
+ console.warn('Detected wrong value for `debug`: '+ local.req[ local.req.method.toLowerCase() ].debug);
686
+ console.warn('Switching `debug` to `true` as `cacheless` mode is enabled');
687
+ local.req[ local.req.method.toLowerCase() ].debug = true;
688
+ }
689
+ localOptions.debugMode = ( /^true$/i.test(local.req[ local.req.method.toLowerCase() ].debug) ) ? true : false;
690
+ } else if (
691
+ self.isCacheless()
476
692
  && hasViews()
477
- && !isWithoutLayout
478
- && localOptions.debugMode == undefined
693
+ && !isWithoutLayout
694
+ && localOptions.debugMode == undefined
479
695
  ) {
480
696
  localOptions.debugMode = true;
481
697
  } else if ( localOptions.debugMode == undefined ) {
482
698
  localOptions.debugMode = self.isCacheless()
483
699
  }
484
-
700
+
485
701
  try {
486
- data = getData();
487
-
702
+
488
703
  if (!userData) {
489
704
  userData = { page: { view: {}}}
490
705
  } else if ( userData && !userData['page']) {
@@ -502,9 +717,11 @@ function SuperController(options) {
502
717
  if ( isWithoutLayout ) {
503
718
  localTemplateConf = JSON.clone(localOptions.template);
504
719
  localTemplateConf.javascripts = new Collection(localTemplateConf.javascripts).find({ isCommon: false}, { isCommon: true, name: 'gina' });
505
- localTemplateConf.stylesheets = new Collection(localTemplateConf.stylesheets).find({ isCommon: false}, { isCommon: true, name: 'gina' });
720
+ localTemplateConf.stylesheets = new Collection(localTemplateConf.stylesheets).find({ isCommon: false}, { isCommon: true, name: 'gina' });
506
721
  }
507
722
  setResources(localTemplateConf);
723
+ // localTemplateConf = null;
724
+
508
725
  // Allowing file & ext override
509
726
  if (
510
727
  typeof(local.req.routing.param.file) != 'undefined'
@@ -512,14 +729,14 @@ function SuperController(options) {
512
729
  ) {
513
730
  data.page.view.file = localOptions.file = local.req.routing.param.file
514
731
  }
515
- if (
516
- typeof(local.req.routing.param.ext) != 'undefined'
732
+ if (
733
+ typeof(local.req.routing.param.ext) != 'undefined'
517
734
  && data.page.view.ext !== local.req.routing.param.ext
518
735
  ) {
519
736
  data.page.view.ext = localOptions.template.ext = local.req.routing.param.ext
520
737
  }
521
-
522
- file = (isRenderingCustomError) ? localOptions.file : data.page.view.file;
738
+
739
+ // file = (isRenderingCustomError) ? localOptions.file : data.page.view.file;
523
740
 
524
741
  // pre-compiling variables
525
742
  data = merge(data, getData()); // needed !!
@@ -527,15 +744,15 @@ function SuperController(options) {
527
744
  if (typeof(data.page.data) == 'undefined' ) {
528
745
  data.page.data = {}
529
746
  }
530
-
531
747
 
532
- if (
748
+
749
+ if (
533
750
  !local.options.isRenderingCustomError
534
- && typeof(data.page.data.status) != 'undefined'
535
- && !/^2/.test(data.page.data.status)
536
- && typeof(data.page.data.error) != 'undefined'
751
+ && typeof(data.page.data.status) != 'undefined'
752
+ && !/^2/.test(data.page.data.status)
753
+ && typeof(data.page.data.error) != 'undefined'
537
754
  ) {
538
- var statusCode = localOptions.conf.server.coreConfiguration.statusCodes;
755
+ // var statusCode = localOptions.conf.server.coreConfiguration.statusCodes;
539
756
  var errorObject = {
540
757
  status: data.page.data.status,
541
758
  //errors: msg.error || msg.errors || msg,
@@ -546,61 +763,68 @@ function SuperController(options) {
546
763
  if ( typeof(data.page.data.session) != 'undefined' ) {
547
764
  errorObject.session = data.page.data.session;
548
765
  }
549
- self.throwError(errorObject);
550
- return;
766
+
767
+ return self.throwError(errorObject);
551
768
  }
552
769
 
553
- // making path thru [namespace &] file
554
- if ( typeof(localOptions.namespace) != 'undefined' && localOptions.namespace ) {
555
- // excepted for custom paths
556
- if ( !/^(\.|\/|\\)/.test(file) )
557
- file = ''+ file.replace(localOptions.namespace+'-', '');
558
-
559
- // means that rule name === namespace -> pointing to root namespace dir
560
- if (!file || file === localOptions.namespace) {
561
- file = 'index'
562
- }
563
- path = (isRenderingCustomError) ? _(file) : _(localOptions.template.html +'/'+ localOptions.namespace + '/' + file)
564
- } else {
565
- if ( localOptions.path && !/(\?|\#)/.test(localOptions.path) ) {
566
- path = _(localOptions.path);
567
- var re = new RegExp( data.page.view.ext+'$');
568
- if ( data.page.view.ext && re.test(data.page.view.file) ) {
569
- data.page.view.path = path.replace('/'+ data.page.view.file, '');
770
+ // // making path thru [namespace &] file
771
+ // if ( typeof(localOptions.namespace) != 'undefined' && localOptions.namespace ) {
772
+ // // excepted for custom paths
773
+ // var fileNamingConvention = file.replace(localOptions.namespace+'-', '');
774
+ // if ( !/^(\.|\/|\\)/.test(file) && file != fileNamingConvention ) {
775
+ // var _ext = data.page.view.ext;
570
776
 
571
- path = path.replace(re, '');
572
- data.page.view.file = data.page.view.file.replace(re, '');
777
+ // console.warn('file `'+ file +'` used in routing `'+ localOptions.rule +'` does not respect gina naming convention ! You should rename the file `'+ file + _ext +'` to `'+ ''+ fileNamingConvention + _ext +'`');
778
+ // console.warn('The reason you are getting this message is because your filename begeins with `<namespace>-`\n If you don\‘t want to rename, use template path like ./../'+ localOptions.namespace +'/'+file);
779
+ // file = ''+ file.replace(localOptions.namespace+'-', '');
780
+ // }
573
781
 
574
- } else {
575
- data.page.view.path = path.replace('/'+ data.page.view.file, '');
576
- }
577
782
 
578
- } else {
579
- path = (!isRenderingCustomError && !/^(\.|\/|\\)/.test(file))
580
- ? _(localOptions.template.html +'/'+ file)
581
- : file
582
- }
583
- }
783
+ // // means that rule name === namespace -> pointing to root namespace dir
784
+ // if (!file || file === localOptions.namespace) {
785
+ // file = 'index'
786
+ // }
787
+ // path = (isRenderingCustomError) ? _(file) : _(localOptions.template.html +'/'+ localOptions.namespace + '/' + file)
788
+ // } else {
789
+ // if ( localOptions.path && !/(\?|\#)/.test(localOptions.path) ) {
790
+ // path = _(localOptions.path);
791
+ // var re = new RegExp( data.page.view.ext+'$');
792
+ // if ( data.page.view.ext && re.test(data.page.view.file) ) {
793
+ // data.page.view.path = path.replace('/'+ data.page.view.file, '');
794
+
795
+ // path = path.replace(re, '');
796
+ // data.page.view.file = data.page.view.file.replace(re, '');
797
+
798
+ // } else {
799
+ // data.page.view.path = path.replace('/'+ data.page.view.file, '');
800
+ // }
801
+
802
+ // } else {
803
+ // path = (!isRenderingCustomError && !/^(\.|\/|\\)/.test(file))
804
+ // ? _(localOptions.template.html +'/'+ file)
805
+ // : file
806
+ // }
807
+ // }
584
808
 
585
- if (data.page.view.ext && !new RegExp(data.page.view.ext+ '$').test(file) /** && hasViews() && fs.existsSync(_(path + data.page.view.ext, true))*/ ) {
586
- path += data.page.view.ext
587
- }
809
+ // if (data.page.view.ext && !new RegExp(data.page.view.ext+ '$').test(file) /** && hasViews() && fs.existsSync(_(path + data.page.view.ext, true))*/ ) {
810
+ // path += data.page.view.ext
811
+ // }
588
812
 
589
- data.page.view.path = path;
813
+ // data.page.view.path = path;
590
814
 
591
815
  var dic = {}, msg = '';
592
- for (var d in data.page) {
816
+ for (let d in data.page) {
593
817
  dic['page.'+d] = data.page[d]
594
818
  }
595
819
 
596
-
820
+
597
821
 
598
822
  // please, do not start with a slashe when including...
599
823
  // ex.:
600
824
  // /html/inc/_partial.html (BAD)
601
825
  // html/inc/_partial.html (GOOD)
602
826
  // ./html/namespace/page.html (GOOD)
603
-
827
+
604
828
  if ( !fs.existsSync(path) ) {
605
829
  msg = 'could not open "'+ path +'"' +
606
830
  '\n1) The requested file does not exists in your templates/html (check your template directory). Can you find: '+path +
@@ -614,32 +838,32 @@ function SuperController(options) {
614
838
  self.throwError(err);
615
839
  return;
616
840
  }
617
-
618
- var isProxyHost = (
619
- typeof(local.req.headers.host) != 'undefined'
620
- && localOptions.conf.server.scheme +'://'+ local.req.headers.host != localOptions.conf.hostname
621
- || typeof(local.req.headers[':authority']) != 'undefined'
622
- && localOptions.conf.server.scheme +'://'+ local.req.headers[':authority'] != localOptions.conf.hostname
841
+
842
+ var isProxyHost = (
843
+ typeof(local.req.headers.host) != 'undefined'
844
+ && localOptions.conf.server.scheme +'://'+ local.req.headers.host != localOptions.conf.hostname
845
+ || typeof(local.req.headers[':authority']) != 'undefined'
846
+ && localOptions.conf.server.scheme +'://'+ local.req.headers[':authority'] != localOptions.conf.hostname
623
847
  ) ? true : false;
624
- // setup swig default filters
848
+ // setup swig default filters
625
849
  var filters = SwigFilters({
626
850
  options : JSON.clone(localOptions),
627
851
  isProxyHost : isProxyHost,
628
852
  throwError : self.throwError,
629
853
  req : local.req,
630
- res : local.res
854
+ res : local.res
631
855
  });
632
856
 
633
857
  try {
634
-
858
+
635
859
  // Extends default `length` filter
636
860
  swig.setFilter('length', filters.length);
637
861
 
638
-
862
+
639
863
 
640
864
  // Allows you to get a bundle web root
641
865
  swig.setFilter('getWebroot', filters.getWebroot);
642
-
866
+
643
867
  swig.setFilter('getUrl', filters.getUrl);
644
868
 
645
869
  } catch (err) {
@@ -651,11 +875,10 @@ function SuperController(options) {
651
875
  self.throwError(local.res, 500, new Error('template compilation exception encoutered: [ '+path+' ]\n'+(err.stack||err.message)));
652
876
  return;
653
877
  }
654
-
655
-
656
-
657
- var layoutPath = null
658
- , assets = null
878
+
879
+
880
+
881
+ var assets = null
659
882
  , mapping = null
660
883
  , XHRData = null
661
884
  , XHRView = null
@@ -665,26 +888,26 @@ function SuperController(options) {
665
888
  , isWithSwigLayout = null
666
889
  , isUsingGinaLayout = (!isWithoutLayout && typeof(localOptions.template.layout) != 'undefined' && fs.existsSync(local.options.template.layout)) ? true : false
667
890
  ;
668
-
669
- if ( isWithoutLayout || isUsingGinaLayout ) {
891
+
892
+ if ( isWithoutLayout || isUsingGinaLayout ) {
670
893
  layoutPath = (isWithoutLayout) ? localOptions.template.noLayout : localOptions.template.layout;
671
894
  // user layout override
672
- if ( isUsingGinaLayout && !isWithoutLayout ) {
895
+ if ( isUsingGinaLayout && !isWithoutLayout ) {
673
896
  layoutPath = localOptions.template.layout;
674
- }
897
+ }
675
898
  if (isWithoutLayout) {
676
899
  data.page.view.layout = layoutPath;
677
- }
900
+ }
678
901
  } else { // without layout case
679
-
902
+
680
903
  // by default
681
904
  layoutPath = localOptions.template.layout;
682
905
  if ( !/^\//.test(layoutPath)) {
683
906
  layoutPath = localOptions.template.templates +'/'+ layoutPath;
684
907
  }
685
908
  // default layout
686
- if (
687
- !isWithoutLayout && !fs.existsSync(layoutPath) && layoutPath == localOptions.template.templates +'/index.html'
909
+ if (
910
+ !isWithoutLayout && !fs.existsSync(layoutPath) && layoutPath == localOptions.template.templates +'/index.html'
688
911
  ) {
689
912
  console.warn('Layout '+ local.options.template.layout +' not found, replacing with `nolayout`: '+ localOptions.template.noLayout);
690
913
  layoutPath = localOptions.template.noLayout
@@ -703,57 +926,57 @@ function SuperController(options) {
703
926
  self.throwError(err);
704
927
  return;
705
928
  }
706
-
929
+
707
930
  }
708
-
709
-
931
+
932
+
710
933
  var isLoadingPartial = false;
711
- try {
934
+ try {
712
935
  assets = {assets:"${assets}"};
713
-
936
+
714
937
  /**
715
938
  * retrieve template & layout
716
- * */
717
- var tpl = null;
939
+ * */
940
+ var tpl = null;
718
941
  // tpl = fs.readFileSync(path).toString();
719
- // layout = fs.readFileSync(layoutPath).toString();
720
-
942
+ // layout = fs.readFileSync(layoutPath).toString();
943
+
721
944
  await Promise.all([
722
- readFile(layoutPath),
723
- readFile(path)
945
+ readFile(layoutPath),
946
+ readFile(path)
724
947
  ])
725
- .then(([_layout, _tpl]) => {
948
+ .then(([_layout, _tpl]) => {
726
949
  layout = _layout.toString();
727
950
  tpl = _tpl.toString();
728
951
  })
729
952
  .catch(error => {
730
- console.error(error.message);
731
- return;
732
- });
733
-
734
-
953
+ console.error(error.message);
954
+ return;
955
+ });
956
+
957
+
735
958
  // mappin conf
736
959
  mapping = { filename: path };
737
960
  if (isRenderingCustomError) {
738
961
  // TODO - Test if there is a block call `gina-error` in the layout & replace block name from tpl
739
-
962
+
740
963
  if ( !/\{\%(\s+extends|extends)/.test(tpl) ) {
741
964
  tpl = "\n{% extends '"+ layoutPath +"' %}\n" + tpl;
742
965
  }
743
966
  if (!/\{\% block content/.test(tpl)) {
744
967
  // TODO - test if lyout has <body>
745
968
  tpl = '{% block content %}<p>If you view this message you didn’t define a content block in your template.</p>{% endblock %}' + tpl;
746
- }
747
-
969
+ }
970
+
748
971
  tpl = tpl.replace(/\{\{ page\.content \}\}/g, '');
749
972
  }
750
-
973
+
751
974
  if ( isWithoutLayout || isWithSwigLayout) {
752
- layout = tpl;
975
+ layout = tpl;
753
976
  } else if (isUsingGinaLayout) {
754
977
  mapping = { filename: path };
755
978
  if ( /(\{\{|\{\{\s+)page\.content/.test(layout) ) {
756
-
979
+
757
980
  if ( /\{\%(\s+extends|extends)/.test(tpl) ) {
758
981
  err = new Error('You cannot use at the same time `page.content` in your layout `'+ layoutPath +'` while calling `extends` from your page or content `'+ path +'`. You have to choose one or the other');
759
982
  self.throwError(local.res, 500, err);
@@ -761,9 +984,9 @@ function SuperController(options) {
761
984
  }
762
985
  layout = layout.replace('{{ page.content }}', tpl);
763
986
  } else {
764
- layout = layout.replace(/\<\/body\>/i, '\t'+tpl+'\n</body>');
987
+ layout = layout.replace(/\<\/body\>/i, '\t'+tpl+'\n</body>');
765
988
  }
766
-
989
+
767
990
  } else {
768
991
  tpl = tpl.replace('{{ page.view.layout }}', data.page.view.layout);
769
992
  if (/\<\/body\>/i.test(layout)) {
@@ -771,178 +994,205 @@ function SuperController(options) {
771
994
  }
772
995
  else {
773
996
  layout += tpl;
774
- }
997
+ }
775
998
  }
776
-
999
+
777
1000
  // precompilation needed in case of `extends` or in order to display the toolbar
778
- if ( hasViews() && self.isCacheless() || /\{\%(\s+extends|extends)/.test(layout) ) {
1001
+ if ( hasViews() && self.isCacheless() || /\{\%(\s+extends|extends)/.test(layout) ) {
779
1002
  layout = swig.compile(layout, mapping)(data);
780
1003
  }
781
- //dic['page.content'] = layout;
782
-
1004
+ //dic['page.content'] = layout;
1005
+
1006
+ tpl = null;
1007
+
783
1008
  } catch(err) {
784
1009
  err.stack = 'Exception, bad syntax or undefined data found: start investigating in '+ mapping.filename +'\n' + err.stack;
785
- self.throwError(local.res, 500, err);
786
- return
1010
+ return self.throwError(local.res, 500, err);
787
1011
  }
788
-
789
- isLoadingPartial = (
790
- !/\<html/i.test(layout)
791
- || !/\<head/i.test(layout)
792
- || !/\<body/i.test(layout)
1012
+ mapping = null;
1013
+ filename = null;
1014
+
1015
+ isLoadingPartial = (
1016
+ !/\<html/i.test(layout)
1017
+ || !/\<head/i.test(layout)
1018
+ || !/\<body/i.test(layout)
793
1019
  ) ? true : false;
794
-
1020
+
795
1021
  // if (isLoadingPartial) {
796
1022
  // console.warn('----------------> loading partial `'+ path);
797
1023
  // }
798
-
799
- isDeferModeEnabled = localOptions.template.javascriptsDeferEnabled || localOptions.conf.content.templates._common.javascriptsDeferEnabled || false;
800
-
1024
+
1025
+ isDeferModeEnabled = localOptions.template.javascriptsDeferEnabled || localOptions.conf.content.templates._common.javascriptsDeferEnabled || false;
1026
+
801
1027
  // iframe case - without HTML TAG
802
1028
  if (!self.isXMLRequest() && !/\<html/.test(layout) ) {
803
1029
  layout = '<html>\n\t<head></head>\n\t<body class="gina-iframe-body">\n\t\t'+ layout +'\n\t</body>\n</html>';
804
- }
805
-
1030
+ }
1031
+
806
1032
  // adding stylesheets
807
1033
  if (!isWithoutLayout && data.page.view.stylesheets && !/\{\{\s+(page\.view\.stylesheets)\s+\}\}/.test(layout) ) {
808
1034
  layout = layout.replace(/\<\/head\>/i, '\n\t{{ page.view.stylesheets }}\n</head>')
809
1035
  }
810
-
1036
+
811
1037
  if (hasViews() && isWithoutLayout) {
812
1038
  // $.getScript(...)
813
1039
  //var isProxyHost = ( typeof(local.req.headers.host) != 'undefined' && localOptions.conf.server.scheme +'://'+ local.req.headers.host != localOptions.conf.hostname || typeof(local.req.headers[':authority']) != 'undefined' && localOptions.conf.server.scheme +'://'+ local.req.headers[':authority'] != localOptions.conf.hostname ) ? true : false;
814
1040
  //var hostname = (isProxyHost) ? localOptions.conf.hostname.replace(/\:\d+$/, '') : localOptions.conf.hostname;
815
-
816
-
817
-
1041
+
1042
+
1043
+
818
1044
  var scripts = data.page.view.scripts;
819
1045
  scripts = scripts.replace(/\s+\<script/g, '\n<script');
820
-
1046
+
821
1047
  if (!isProxyHost) {
822
1048
  var webroot = data.page.environment.webroot;
823
1049
  scripts = scripts.replace(/src\=\"\/(.*)\"/g, 'src="'+ webroot +'$1"');
824
1050
  //stylesheets = stylesheets.replace(/href\=\"\/(.*)\"/g, 'href="'+ webroot +'$1"')
1051
+ webroot = null;
825
1052
  }
826
-
1053
+
827
1054
  // iframe case - without HTML TAG
828
- if (self.isXMLRequest() || !/\<html/.test(layout) ) {
829
- layout += scripts;
830
- //layout += stylesheets;
831
- }
832
-
1055
+ if (self.isXMLRequest() || !/\<html/.test(layout) ) {
1056
+ layout += scripts;
1057
+ //layout += stylesheets;
1058
+ }
1059
+
833
1060
  }
834
1061
 
835
1062
  // adding plugins
836
-
837
-
1063
+ // means that we don't want GFF context or we already have it loaded
1064
+ viewInfos = JSON.clone(data.page.view);
1065
+ if ( !isWithoutLayout )
1066
+ viewInfos.assets = assets;
1067
+
838
1068
  if (
839
- hasViews() && self.isCacheless() && !isWithoutLayout
840
- && localOptions.debugMode
841
- ||
842
- hasViews() && self.isCacheless() && !isWithoutLayout
843
- && typeof(localOptions.debugMode) == 'undefined'
844
- ||
845
- hasViews() && localOptions.debugMode
1069
+ hasViews() && self.isCacheless() && !isWithoutLayout
1070
+ && localOptions.debugMode
1071
+ ||
1072
+ hasViews() && self.isCacheless() && !isWithoutLayout
1073
+ && typeof(localOptions.debugMode) == 'undefined'
1074
+ ||
1075
+ hasViews() && localOptions.debugMode
846
1076
  ) {
847
1077
 
848
1078
  layout = ''
1079
+ // + '{%- set ginaDataInspector = JSON.clone(page) -%}'
849
1080
  + '{%- set ginaDataInspector = JSON.clone(page) -%}'
1081
+ // + '{%- set ginaDataInspector = { view: {}, environment: { routing: {}}} -%}'
850
1082
  + '{%- set ginaDataInspector.view.assets = {} -%}'
851
1083
  + '{%- set ginaDataInspector.view.scripts = "ignored-by-toolbar" -%}'
852
1084
  + '{%- set ginaDataInspector.view.stylesheets = "ignored-by-toolbar" -%}'
853
1085
  + layout
854
1086
  ;
855
-
1087
+
856
1088
  plugin = '\t'
857
1089
  + '{# Gina Toolbar #}'
858
1090
  + '{%- set userDataInspector = JSON.clone(page) -%}'
1091
+ // + '{%- set userDataInspector = { view: {}, environment: { routing: {}}} -%}'
859
1092
  + '{%- set userDataInspector.view.scripts = "ignored-by-toolbar" -%}'
860
1093
  + '{%- set userDataInspector.view.stylesheets = "ignored-by-toolbar" -%}'
861
1094
  + '{%- set userDataInspector.view.assets = '+ JSON.stringify(assets) +' -%}'
862
- + '{%- include "'+ getPath('gina').core +'/asset/js/plugin/src/gina/toolbar/toolbar.html" with { gina: ginaDataInspector, user: userDataInspector } -%}'
863
- + '{# END Gina Toolbar #}'
1095
+ + '{%- include "'+ getPath('gina').core +'/asset/plugin/dist/vendor/gina/html/toolbar.html" with { gina: ginaDataInspector, user: userDataInspector } -%}'// jshint ignore:line
1096
+ + '{# END Gina Toolbar #}'
864
1097
  ;
865
-
1098
+
866
1099
 
867
1100
  if (isWithoutLayout && localOptions.debugMode || localOptions.debugMode ) {
868
1101
 
869
- XHRData = '\t<input type="hidden" id="gina-without-layout-xhr-data" value="'+ encodeURIComponent(JSON.stringify(data.page.data)) +'">\n\r';
870
-
871
- layout = layout.replace(/<\/body>/i, XHRData + '\n\t</body>');
1102
+ if (self.isXMLRequest()) {
1103
+ XHRData = '\t<input type="hidden" id="gina-without-layout-xhr-data" value="'+ encodeRFC5987ValueChars(JSON.stringify(data.page.data)) +'">\n\r';
1104
+ XHRView = '\n<input type="hidden" id="gina-without-layout-xhr-view" value="'+ encodeRFC5987ValueChars(JSON.stringify(viewInfos)) +'">';
1105
+ if ( /<\/body>/i.test(layout) ) {
1106
+ layout = layout.replace(/<\/body>/i, XHRData + XHRView + '\n\t</body>');
1107
+ } else {
1108
+ // Popin case
1109
+ // Fix added on 2023-01-25
1110
+ layout += XHRData + XHRView + '\n\t'
1111
+ }
1112
+ }
1113
+
1114
+
872
1115
  }
873
-
1116
+
874
1117
  if (self.isCacheless() || localOptions.debugMode ) {
875
1118
  layout = layout.replace(/<\/body>/i, plugin + '\n\t</body>');
876
1119
  }
877
-
1120
+
878
1121
  // adding javascripts
879
- layout.replace('{{ page.view.scripts }}', '');
1122
+ layout.replace('{{ page.view.scripts }}', '');
880
1123
  // placed in the HEAD excepted when rendering a partial or when `isDeferModeEnabled` == true
881
1124
  if (isLoadingPartial) {
882
1125
  layout += '\t{{ page.view.scripts }}';
883
1126
  } else {
884
1127
  if ( isDeferModeEnabled ) {
885
1128
  layout = layout.replace(/\<\/head\>/i, '\t{{ page.view.scripts }}\n\t</head>');
886
- } else { // placed in the BODY
1129
+ } else { // placed in the BODY
887
1130
  layout = layout.replace(/\<\/body\>/i, '\t{{ page.view.scripts }}\n</body>');
888
1131
  }
889
1132
  }
890
-
1133
+
891
1134
  // ginaLoader cannot be deferred
892
1135
  if ( !localOptions.template.javascriptsExcluded || localOptions.template.javascriptsExcluded != '**' ) {
893
- layout = layout.replace(/\<\/head\>/i, '\t'+ localOptions.template.ginaLoader +'\n</head>');
1136
+ layout = layout.replace(/\<\/head\>/i, '\t'+ localOptions.template.ginaLoader +'\n</head>');
894
1137
  }
895
1138
 
896
1139
  } else if ( hasViews() && self.isCacheless() && self.isXMLRequest() ) {
897
-
898
- if (isWithoutLayout) {
1140
+
1141
+ if (isWithoutLayout) {
899
1142
  delete data.page.view.scripts;
900
- delete data.page.view.stylesheets;
1143
+ delete data.page.view.stylesheets;
901
1144
  }
902
1145
  // means that we don't want GFF context or we already have it loaded
903
- viewInfos = JSON.clone(data.page.view);
904
- if ( !isWithoutLayout )
905
- viewInfos.assets = assets;
1146
+ // viewInfos = JSON.clone(data.page.view);
1147
+ // if ( !isWithoutLayout )
1148
+ // viewInfos.assets = assets;
906
1149
 
907
- XHRData = '\n<input type="hidden" id="gina-without-layout-xhr-data" value="'+ encodeURIComponent(JSON.stringify(data.page.data)) +'">';
908
- XHRView = '\n<input type="hidden" id="gina-without-layout-xhr-view" value="'+ encodeURIComponent(JSON.stringify(viewInfos)) +'">';
909
1150
 
1151
+ XHRData = '\n<input type="hidden" id="gina-without-layout-xhr-data" value="'+ encodeRFC5987ValueChars(JSON.stringify(data.page.data)) +'">';
1152
+ XHRView = '\n<input type="hidden" id="gina-without-layout-xhr-view" value="'+ encodeRFC5987ValueChars(JSON.stringify(viewInfos)) +'">';
1153
+ if ( /<\/body>/i.test(layout) ) {
1154
+ layout = layout.replace(/<\/body>/i, XHRData + XHRView + '\n\t</body>');
1155
+ } else {
1156
+ // Popin case
1157
+ // Fix added on 2023-01-25
1158
+ layout += XHRData + XHRView + '\n\t'
1159
+ }
910
1160
 
911
- layout += XHRData + XHRView;
1161
+ // layout += XHRData + XHRView;
912
1162
 
913
1163
  } else { // other envs like prod ...
914
-
1164
+
915
1165
  // adding javascripts
916
1166
  // cleanup first
917
- layout.replace('{{ page.view.scripts }}', '');
1167
+ layout.replace('{{ page.view.scripts }}', '');
918
1168
  // placed in the HEAD excepted when rendering a partial or when `isDeferModeEnabled` == true
919
1169
  // if (isLoadingPartial) {
920
1170
  // layout += '\t{{ page.view.scripts }}';
921
1171
  // } else {
922
1172
  // if ( isDeferModeEnabled ) {
923
1173
  // layout = layout.replace(/\<\/head\>/i, '\t{{ page.view.scripts }}\n\t</head>');
924
- // } else { // placed in the BODY
1174
+ // } else { // placed in the BODY
925
1175
  // layout = layout.replace(/\<\/body\>/i, '\t{{ page.view.scripts }}\n</body>');
926
1176
  // }
927
1177
  // }
928
-
1178
+
929
1179
  // // ginaLoader cannot be deferred
930
1180
  // if ( !localOptions.template.javascriptsExcluded || localOptions.template.javascriptsExcluded != '**' ) {
931
- // layout = layout.replace(/\<\/head\>/i, '\t'+ localOptions.template.ginaLoader +'\n</head>');
1181
+ // layout = layout.replace(/\<\/head\>/i, '\t'+ localOptions.template.ginaLoader +'\n</head>');
932
1182
  // }
933
-
1183
+
934
1184
  // adding javascripts
935
1185
  layout.replace('{{ page.view.scripts }}', '');
936
- if (isLoadingPartial) {
1186
+ if (isLoadingPartial) {
937
1187
  layout += '\t{{ page.view.scripts }}\n';
938
1188
  if ( !localOptions.template.javascriptsExcluded || localOptions.template.javascriptsExcluded != '**' ) {
939
1189
  layout += '\t'+ localOptions.template.ginaLoader +'\n';
940
1190
  }
941
1191
  } else {
942
- if ( isDeferModeEnabled && /\<\/head\>/i.test(layout) ) { // placed in the HEAD
1192
+ if ( isDeferModeEnabled && /\<\/head\>/i.test(layout) ) { // placed in the HEAD
943
1193
  layout = layout.replace(/\<\/head\>/i, '\t{{ page.view.scripts }}\n\t</head>');
944
-
945
- } else { // placed in the BODY
1194
+
1195
+ } else { // placed in the BODY
946
1196
  layout = layout.replace(/\<\/body\>/i, '\t{{ page.view.scripts }}\n</body>');
947
1197
  }
948
1198
  // ginaLoader cannot be deferred
@@ -951,20 +1201,20 @@ function SuperController(options) {
951
1201
  }
952
1202
  }
953
1203
  }
954
-
955
-
1204
+
1205
+
956
1206
  layout = whisper(dic, layout, /\{{ ([a-zA-Z.]+) \}}/g );
957
1207
  dic['page.content'] = layout;
958
1208
  /**
959
1209
  // special case for template without layout in debug mode - dev only
960
1210
  if ( hasViews() && localOptions.debugMode && self.isCacheless() && !/\{\# Gina Toolbar \#\}/.test(layout) ) {
961
- try {
962
-
963
- layout = layout.replace(/<\/body>/i, plugin + '\n\t</body>');
1211
+ try {
1212
+
1213
+ layout = layout.replace(/<\/body>/i, plugin + '\n\t</body>');
964
1214
  layout = whisper(dic, layout, /\{{ ([a-zA-Z.]+) \}}/g );
965
1215
  //swig.invalidateCache();
966
- layout = swig.compile(layout, mapping)(data);
967
-
1216
+ layout = swig.compile(layout, mapping)(swigData);
1217
+
968
1218
 
969
1219
  } catch (err) {
970
1220
  filename = localOptions.template.html;
@@ -972,22 +1222,23 @@ function SuperController(options) {
972
1222
  self.throwError(local.res, 500, new Error('Compilation error encountered while trying to process template `'+ filename + '`\n'+(err.stack||err.message)));
973
1223
  return;
974
1224
  }
975
- }
1225
+ }
976
1226
  else if (hasViews() && localOptions.debugMode && self.isCacheless()) {
977
1227
  try {
978
1228
  //layout = whisper(dic, layout, /\{{ ([a-zA-Z.]+) \}}/g );
979
- layout = swig.compile(layout, mapping)(data);
1229
+ layout = swig.compile(layout, mapping)(swigData);
980
1230
  } catch (err) {
981
1231
  filename = localOptions.template.html;
982
1232
  filename += ( typeof(data.page.view.namespace) != 'undefined' && data.page.view.namespace != '' && new RegExp('^' + data.page.view.namespace +'-').test(data.page.view.file) ) ? '/' + data.page.view.namespace + data.page.view.file.split(data.page.view.namespace +'-').join('/') + ( (data.page.view.ext != '') ? data.page.view.ext: '' ) : '/' + data.page.view.file+ ( (data.page.view.ext != '') ? data.page.view.ext: '' );
983
1233
  self.throwError(local.res, 500, new Error('Compilation error encountered while trying to process template `'+ filename + '`\n'+(err.stack||err.message)));
984
1234
  return;
985
1235
  }
986
- }
987
- */
988
-
1236
+ }
1237
+ */
1238
+
989
1239
 
990
- if ( !local.res.headersSent ) {
1240
+ // if ( !local.res.headersSent ) {
1241
+ if ( !headersSent() ) {
991
1242
  local.res.statusCode = ( typeof(localOptions.conf.server.coreConfiguration.statusCodes[data.page.data.status]) != 'undefined' ) ? data.page.data.status : 200; // by default
992
1243
  //catching errors
993
1244
  if (
@@ -1004,78 +1255,93 @@ function SuperController(options) {
1004
1255
  }
1005
1256
 
1006
1257
  local.res.setHeader('content-type', localOptions.conf.server.coreConfiguration.mime['html'] + '; charset='+ localOptions.conf.encoding );
1007
-
1258
+
1008
1259
  try {
1009
-
1260
+
1010
1261
  // escape special chars
1011
1262
  var blacklistRe = new RegExp('[\<\>]', 'g');
1012
1263
  // DO NOT REPLACE IT BY JSON.clone() !!!!
1013
-
1264
+
1014
1265
  data.page.data = JSON.parse(JSON.stringify(data.page.data).replace(blacklistRe, '\$&'));
1015
-
1266
+ blacklistRe = null;
1016
1267
  } catch (err) {
1017
1268
  filename = localOptions.template.html;
1018
1269
  filename += ( typeof(data.page.view.namespace) != 'undefined' && data.page.view.namespace != '' && new RegExp('^' + data.page.view.namespace +'-').test(data.page.view.file) ) ? '/' + data.page.view.namespace + data.page.view.file.split(data.page.view.namespace +'-').join('/') + ( (data.page.view.ext != '') ? data.page.view.ext: '' ) : '/' + data.page.view.file+ ( (data.page.view.ext != '') ? data.page.view.ext: '' );
1019
1270
  self.throwError(local.res, 500, new Error('Controller::render(...) compilation error encountered while trying to process template `'+ filename + '`\n' + (err.stack||err.message||err) ));
1271
+ filename = null;
1272
+ blacklistRe = null;
1020
1273
  return;
1021
1274
  }
1022
-
1023
-
1275
+
1276
+
1277
+
1024
1278
  // Only available for http/2.0 for now
1025
1279
  if ( !self.isXMLRequest() && /http\/2/.test(localOptions.conf.server.protocol) ) {
1280
+ var assets = null;
1026
1281
  try {
1027
- // TODO - button in toolbar to empty url assets cache
1282
+ // TODO - button in toolbar to empty url assets cache
1028
1283
  if ( /** self.isCacheless() ||*/ typeof(localOptions.template.assets) == 'undefined' || typeof(localOptions.template.assets[local.req.url]) == 'undefined' ) {
1029
1284
  // assets string -> object
1030
1285
  //assets = self.serverInstance.getAssets(localOptions.conf, layout.toString(), swig, data);
1031
1286
  assets = self.serverInstance.getAssets(localOptions.conf, layout, swig, data);
1032
1287
  localOptions.template.assets = JSON.parse(assets);
1033
1288
  }
1034
-
1289
+
1035
1290
  // only for toolbar - TODO hasToolbar()
1036
1291
  if (
1037
1292
  self.isCacheless() && hasViews() && !isWithoutLayout
1038
1293
  || hasViews() && localOptions.debugMode
1039
- || self.isCacheless() && hasViews() && self.isXMLRequest()
1040
- ) {
1041
- layout = layout.replace('{"assets":"${assets}"}', assets );
1294
+ || self.isCacheless() && hasViews() && self.isXMLRequest()
1295
+ ) {
1296
+ layout = layout.replace('{"assets":"${assets}"}', assets );
1042
1297
  }
1043
-
1298
+ assets = null;
1299
+
1044
1300
  } catch (err) {
1301
+ assets = null;
1045
1302
  self.throwError(local.res, 500, new Error('Controller::render(...) calling getAssets(...) \n' + (err.stack||err.message||err) ));
1046
1303
  return;
1047
1304
  }
1048
1305
  }
1049
-
1050
- // Last compilation before rendering
1051
- layout = swig.compile(layout, mapping)(data);
1052
-
1053
- if ( !local.res.headersSent ) {
1306
+
1307
+ // Last compilation before rendering
1308
+ // Now we can use `data` instead of `swigData`
1309
+ layout = swig.compile(layout, mapping)(data);
1310
+
1311
+ if ( !headersSent() ) {
1054
1312
  if ( local.options.isRenderingCustomError ) {
1055
1313
  local.options.isRenderingCustomError = false;
1056
1314
  }
1315
+
1057
1316
  local.res.end(layout);
1058
- }
1059
-
1317
+ layout = null;
1318
+ }
1319
+
1060
1320
  console.info(local.req.method +' ['+local.res.statusCode +'] '+ local.req.url);
1061
-
1062
- } else if (typeof(local.next) != 'undefined') {
1063
- // local.next();
1064
- return local.next();
1065
- } else {
1066
- if ( typeof(local.req.params.errorObject) != 'undefined' ) {
1067
- self.throwError(local.req.params.errorObject);
1068
- return;
1321
+
1322
+ if ( typeof(local.next) != 'undefined' ) {
1323
+ return local.next();
1069
1324
  }
1070
- local.res.end('Unexpected controller error while trying to render.');
1071
1325
  return;
1072
1326
  }
1073
- } catch (err) {
1074
- self.throwError(local.res, 500, err);
1327
+
1328
+
1329
+ if ( typeof(local.req.params.errorObject) != 'undefined' ) {
1330
+ return self.throwError(local.req.params.errorObject);
1331
+ }
1332
+ local.res.end('Unexpected controller error while trying to render.');
1333
+
1334
+ if (typeof(local.next) != 'undefined') {
1335
+ return local.next();
1336
+ }
1337
+
1075
1338
  return;
1339
+
1340
+ } catch (err) {
1341
+ return self.throwError(local.res, 500, err);
1076
1342
  }
1077
1343
  }
1078
-
1344
+
1079
1345
 
1080
1346
  this.isXMLRequest = function() {
1081
1347
  return local.options.isXMLRequest;
@@ -1085,6 +1351,13 @@ function SuperController(options) {
1085
1351
  return ( /true/.test(local.options.withCredentials) ) ? true : false;
1086
1352
  }
1087
1353
 
1354
+ this.isPopinContext = function() {
1355
+ return (
1356
+ typeof(local.req.headers['x-gina-popin-id']) != 'undefined'
1357
+ || typeof(local.req.headers['x-gina-popin-name']) != 'undefined'
1358
+ ) ? true : false;
1359
+ }
1360
+
1088
1361
  /**
1089
1362
  * Render JSON
1090
1363
  *
@@ -1102,36 +1375,45 @@ function SuperController(options) {
1102
1375
  return false
1103
1376
  }
1104
1377
  if ( self.isProcessingError ) {
1105
- return;
1378
+ return;
1106
1379
  }
1107
1380
 
1108
1381
  var request = local.req;
1109
1382
  var response = local.res;
1110
1383
  var next = local.next || null;
1111
1384
  // var stream = null;
1112
- // if ( /http\/2/.test(local.options.conf.server.protocol) ) {
1113
- // stream = response.stream;
1385
+ // if ( /http\/2/.test(local.options.conf.server.protocol) ) {
1386
+ // stream = response.stream;
1114
1387
  // }
1115
1388
 
1389
+ // Added on 2023-06-12
1390
+ if ( headersSent(response) ) {
1391
+ freeMemory([jsonObj, request, response, next]);
1392
+ return;
1393
+ }
1394
+
1116
1395
  if (!jsonObj) {
1117
1396
  jsonObj = {}
1118
1397
  }
1119
-
1398
+
1120
1399
  try {
1121
1400
  // just in case
1122
1401
  if ( typeof(jsonObj) == 'string') {
1123
1402
  jsonObj = JSON.parse(jsonObj)
1124
1403
  }
1404
+ var data = JSON.stringify(jsonObj);
1125
1405
 
1126
1406
  // if( typeof(local.options) != "undefined" && typeof(local.options.charset) != "undefined" ){
1127
1407
  // response.setHeader("charset", local.options.charset);
1128
1408
  // }
1129
-
1409
+
1130
1410
 
1131
1411
  //catching errors
1132
1412
  if (
1133
1413
  typeof(jsonObj.errno) != 'undefined' && response.statusCode == 200
1134
- || typeof(jsonObj.status) != 'undefined' && jsonObj.status != 200 && typeof(local.options.conf.server.coreConfiguration.statusCodes[jsonObj.status]) != 'undefined'
1414
+ ||
1415
+ typeof(jsonObj.status) != 'undefined' && jsonObj.status != 200
1416
+ && typeof(local.options.conf.server.coreConfiguration.statusCodes[jsonObj.status]) != 'undefined'
1135
1417
  ) {
1136
1418
 
1137
1419
  try {
@@ -1151,73 +1433,61 @@ function SuperController(options) {
1151
1433
  response.setHeader('content-type', local.options.conf.server.coreConfiguration.mime['json'] + '; charset='+ local.options.conf.encoding)
1152
1434
  }
1153
1435
 
1154
- if ( !response.headersSent ) {
1436
+ // if ( !headersSent(response) ) {
1155
1437
  console.info(request.method +' ['+ response.statusCode +'] '+ request.url);
1156
1438
 
1439
+
1157
1440
  if ( local.options.isXMLRequest && self.isWithCredentials() ) {
1158
1441
 
1159
- var data = JSON.stringify(jsonObj);
1160
- var len = 0;
1161
1442
  // content length must be the right size !
1162
- if ( typeof(data) === 'string') {
1163
- len = Buffer.byteLength(data, 'utf8')
1164
- } else {
1165
- len = data.length
1166
- }
1167
-
1168
- if (!response.headersSent)
1443
+ var len = Buffer.byteLength(data, 'utf8') || 0;
1444
+ if ( !headersSent(response) ) {
1169
1445
  response.setHeader("content-length", len);
1170
-
1171
-
1172
- // if (stream && !stream.destroyed) {
1173
- // //stream.respond(header);
1174
- // stream.end(data);
1175
- // } else {
1176
- response.write(data);
1177
-
1178
- // required to close connection
1179
- setTimeout(function () {
1180
- response.end();
1181
- try {
1182
- response.headersSent = true;
1183
- } catch(err) {
1184
- // Ignoring warning
1185
- //console.warn(err);
1186
- }
1187
-
1188
- if ( next ) {
1189
- next()
1190
- }
1191
- }, 200);
1192
-
1193
-
1194
-
1195
- return // force completion
1196
- // }
1197
-
1446
+ }
1198
1447
 
1199
- } else { // normal case
1200
- response.end(JSON.stringify(jsonObj));
1201
- if (!response.headersSent) {
1448
+ response.write(data);
1449
+
1450
+ // required to close connection
1451
+ setTimeout(function () {
1452
+ response.end();
1202
1453
  try {
1203
1454
  response.headersSent = true;
1204
1455
  } catch(err) {
1205
1456
  // Ignoring warning
1206
1457
  //console.warn(err);
1207
1458
  }
1459
+
1460
+ if ( next ) {
1461
+ next()
1462
+ }
1463
+
1464
+ freeMemory([jsonObj, data, request, response, next]);
1465
+ }, 200);
1466
+
1467
+ // force completion
1468
+ return
1469
+ }
1470
+ // normal case
1471
+ response.end(JSON.stringify(jsonObj));
1472
+ if (!headersSent(response)) {
1473
+ try {
1474
+ response.headersSent = true;
1475
+ } catch(err) {
1476
+ // Ignoring warning
1477
+ //console.warn(err);
1208
1478
  }
1209
- if ( next ) {
1210
- next()
1211
- }
1212
-
1213
- return;
1214
1479
  }
1215
- }
1480
+ if ( next ) {
1481
+ return next()
1482
+ }
1483
+
1484
+ freeMemory([jsonObj, data, request, response, next]);
1485
+
1486
+ return;
1487
+ // }
1216
1488
  } catch (err) {
1217
- self.throwError(response, 500, err);
1218
- return;
1489
+ return self.throwError(response, 500, err);
1219
1490
  }
1220
-
1221
1491
  }
1222
1492
 
1223
1493
 
@@ -1227,33 +1497,52 @@ function SuperController(options) {
1227
1497
  if (local.options.renderingStack.length > 1) {
1228
1498
  return false
1229
1499
  }
1500
+ if ( self.isProcessingError ) {
1501
+ return;
1502
+ }
1503
+
1504
+ var request = local.req;
1505
+ var response = local.res;
1506
+ var next = local.next || null;
1507
+ // var stream = null;
1508
+ // if ( /http\/2/.test(local.options.conf.server.protocol) ) {
1509
+ // stream = response.stream;
1510
+ // }
1511
+
1512
+ // Added on 2023-06-12
1513
+ if ( headersSent(response) ) {
1514
+ freeMemory([content, request, response, next]);
1515
+ return;
1516
+ }
1230
1517
 
1231
1518
  if ( typeof(content) != "string" ) {
1232
1519
  content = content.toString();
1233
1520
  }
1234
1521
 
1235
1522
  // if (typeof(options) != "undefined" && typeof(options.charset) !="undefined") {
1236
- // local.res.setHeader("charset", options.charset);
1523
+ // response.setHeader("charset", options.charset);
1237
1524
  // }
1238
- if ( !local.res.getHeaders()['content-type'] ) {
1239
- local.res.setHeader('content-type', 'text/plain' + '; charset='+ local.options.conf.encoding);
1525
+ if ( !response.getHeaders()['content-type'] ) {
1526
+ response.setHeader('content-type', 'text/plain' + '; charset='+ local.options.conf.encoding);
1240
1527
  }
1241
1528
 
1242
- if ( !local.res.headersSent ) {
1243
- console.info(local.req.method +' ['+local.res.statusCode +'] '+ local.req.url);
1244
- local.res.end(content);
1529
+ if ( !headersSent() ) {
1530
+ console.info(request.method +' ['+response.statusCode +'] '+ request.url);
1531
+ response.end(content);
1245
1532
  try {
1246
- local.res.headersSent = true
1533
+ response.headersSent = true
1247
1534
  } catch(err) {
1248
1535
  // Ignoring warning
1249
1536
  //console.warn(err);
1250
1537
  }
1538
+
1539
+ freeMemory([jsonObj, data, request, response, next]);
1251
1540
  }
1252
1541
  }
1253
1542
 
1254
1543
  var parseDataObject = function(o, obj, override) {
1255
1544
 
1256
- for (var i in o) {
1545
+ for (let i in o) {
1257
1546
  if ( o[i] !== null && typeof(o[i]) == 'object' || override && o[i] !== null && typeof(o[i]) == 'object' ) {
1258
1547
  parseDataObject(o[i], obj);
1259
1548
  } else if (o[i] == '_content_'){
@@ -1283,14 +1572,14 @@ function SuperController(options) {
1283
1572
  , str = '{'
1284
1573
  , _count = 0;
1285
1574
 
1286
- for (var k = 0, len = keys.length; k<len; ++k) {
1575
+ for (let k = 0, len = keys.length; k<len; ++k) {
1287
1576
  str += "\""+ keys.splice(0,1)[0] + "\":{";
1288
1577
 
1289
1578
  ++_count;
1290
1579
  if (k == len-1) {
1291
1580
  str = str.substr(0, str.length-1);
1292
1581
  str += "\"_content_\"";
1293
- for (var c = 0; c<_count; ++c) {
1582
+ for (let c = 0; c<_count; ++c) {
1294
1583
  str += "}"
1295
1584
  }
1296
1585
  }
@@ -1299,8 +1588,11 @@ function SuperController(options) {
1299
1588
  newObj = parseDataObject(JSON.parse(str), value, override);
1300
1589
  local.userData = merge(local.userData, newObj);
1301
1590
 
1591
+ freeMemory([name, value, keys, newObj, str, _count], false);
1592
+
1302
1593
  } else if ( typeof(local.userData[name]) == 'undefined' ) {
1303
- local.userData[name] = value.replace(/\\/g, '')
1594
+ local.userData[name] = value.replace(/\\/g, '');
1595
+ freeMemory([name, value], false)
1304
1596
  }
1305
1597
  }
1306
1598
 
@@ -1308,7 +1600,7 @@ function SuperController(options) {
1308
1600
  * Get data
1309
1601
  *
1310
1602
  * @param {String} variable Data name to set
1311
- * @returns {Object | String} data Data object or String
1603
+ * @returns {Object | String} data Data object or String
1312
1604
  * */
1313
1605
  var get = function(variable) {
1314
1606
  return local.userData[variable]
@@ -1321,32 +1613,36 @@ function SuperController(options) {
1321
1613
  * */
1322
1614
  var setResources = function(viewConf) {
1323
1615
  if (!viewConf) {
1324
- self.throwError(500, new Error('No views configuration found. Did you try to add views before using Controller::render(...) ? Try to run: gina view:add '+ options.conf.bundle +' @'+ options.conf.projectName));
1325
- return;
1616
+ return self.throwError(500, new Error('No views configuration found. Did you try to add views before using Controller::render(...) ? Try to run: gina view:add '+ options.conf.bundle +' @'+ options.conf.projectName));
1326
1617
  }
1327
-
1618
+
1328
1619
  var authority = ( typeof(local.req.headers['x-forwarded-proto']) != 'undefined' ) ? local.req.headers['x-forwarded-proto'] : local.options.conf.server.scheme;
1329
1620
  authority += '://'+ local.req.headers.host;
1330
1621
  var useWebroot = false;
1331
1622
  if ( !/^\/$/.test(local.options.conf.server.webroot) && local.options.conf.server.webroot.length > 0 && local.options.conf.hostname.replace(/\:\d+$/, '') == authority ) {
1332
1623
  useWebroot = true
1333
1624
  }
1334
-
1625
+ authority = null;
1626
+
1335
1627
  var reURL = new RegExp('^'+ local.options.conf.server.webroot);
1336
1628
 
1337
1629
  var cssStr = '', jsStr = '';
1338
-
1630
+
1339
1631
  //Get css
1340
1632
  if( viewConf.stylesheets ) {
1341
1633
  cssStr = getNodeRes('css', viewConf.stylesheets, useWebroot, reURL)
1342
1634
  }
1343
1635
  //Get js
1344
- if( viewConf.javascripts ) {
1636
+ if( viewConf.javascripts ) {
1345
1637
  jsStr = getNodeRes('js', viewConf.javascripts, useWebroot, reURL)
1346
1638
  }
1347
1639
 
1348
1640
  set('page.view.stylesheets', cssStr);
1349
1641
  set('page.view.scripts', jsStr);
1642
+
1643
+ reURL = null;
1644
+ cssStr = null;
1645
+ jsStr = null;
1350
1646
  }
1351
1647
 
1352
1648
  /**
@@ -1362,7 +1658,7 @@ function SuperController(options) {
1362
1658
  * @private
1363
1659
  * */
1364
1660
  var getNodeRes = function(type, resArr, useWebroot, reURL) {
1365
-
1661
+
1366
1662
  var r = 0
1367
1663
  , rLen = resArr.length
1368
1664
  , obj = null
@@ -1370,7 +1666,7 @@ function SuperController(options) {
1370
1666
  ;
1371
1667
  switch(type){
1372
1668
  case 'css':
1373
- for (; r < rLen; ++r) {
1669
+ for (; r < rLen; ++r) {
1374
1670
  obj = resArr[r];
1375
1671
  if (useWebroot && !reURL.test(obj.url) ) {
1376
1672
  obj.url = local.options.conf.server.webroot + obj.url.substr(1);
@@ -1378,35 +1674,37 @@ function SuperController(options) {
1378
1674
  // TODO - add support for cdn
1379
1675
  if (!/\:\/\//.test(obj.url) ) {
1380
1676
  obj.url = local.options.conf.hostname + obj.url;
1381
- }
1382
-
1677
+ }
1678
+
1383
1679
  if (obj.media)
1384
- str += '\n\t\t<link href="'+ obj.url +'" media="'+ obj.media +'" rel="'+ obj.rel +'" type="'+ obj.type +'">';
1680
+ str += '\n\t\t<link href="'+ obj.url +'" media="'+ obj.media +'" rel="'+ obj.rel +'" type="'+ obj.type +'">';
1385
1681
  else
1386
- str += '\n\t\t<link href="'+ obj.url +'" rel="'+ obj.rel +'" type="'+ obj.type +'">';
1682
+ str += '\n\t\t<link href="'+ obj.url +'" rel="'+ obj.rel +'" type="'+ obj.type +'">';
1387
1683
  }
1388
-
1389
- return str;
1390
- break;
1684
+ break;
1391
1685
 
1392
1686
  case 'js':
1393
1687
  var deferMode = (local.options.template.javascriptsDeferEnabled) ? ' defer' : '';
1394
-
1688
+
1395
1689
  for (; r < rLen; ++r) {
1396
1690
  obj = resArr[r];
1397
1691
  if (useWebroot && !reURL.test(obj.url) ) {
1398
1692
  obj.url = local.options.conf.server.webroot + obj.url.substr(1);
1399
1693
  }
1400
- // TODO - add support for cdn
1694
+ // TODO - add support for cdn
1401
1695
  if (!/\:\/\//.test(obj.url) ) {
1402
1696
  obj.url = local.options.conf.hostname + obj.url;
1403
1697
  }
1404
- str += '\n\t\t<script'+ deferMode +' type="'+ obj.type +'" src="'+ obj.url +'"></script>'
1698
+ str += '\n\t\t<script'+ deferMode +' type="'+ obj.type +'" src="'+ obj.url +'"></script>'
1405
1699
  }
1406
-
1407
- return str;
1408
- break;
1700
+ break;
1409
1701
  }
1702
+ r = null;
1703
+ rLen = null;
1704
+ obj = null;
1705
+
1706
+
1707
+ return str;
1410
1708
  }
1411
1709
 
1412
1710
  /**
@@ -1419,17 +1717,17 @@ function SuperController(options) {
1419
1717
  var getData = function() {
1420
1718
  return refToObj( local.userData )
1421
1719
  }
1422
-
1720
+
1423
1721
 
1424
1722
  var isValidURL = function(url){
1425
- var re = /(http|ftp|https|sftp):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
1426
- return (re.test(url)) ? true : false
1723
+ // var re = /(http|ftp|https|sftp):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
1724
+ return (/(http|ftp|https|sftp):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/.test(url)) ? true : false;
1427
1725
  }
1428
-
1726
+
1429
1727
  /**
1430
- * Set method - Override current method
1728
+ * Set method - Override current method
1431
1729
  * E.g.: in case of redirect, to force PUT to GET
1432
- *
1730
+ *
1433
1731
  * @param {string} requestMethod - GET, POST, PUT, DELETE
1434
1732
  */
1435
1733
  var localRequestMethod = null, localRequestMethodParams = null;
@@ -1438,80 +1736,83 @@ function SuperController(options) {
1438
1736
  if ( /http\/2/i.test(conf.server.protocolShort) ) {
1439
1737
  local.req.headers[':method'] = local.req.method.toUpperCase()
1440
1738
  }
1441
-
1739
+
1442
1740
  localRequestMethod = local.req.method = local.req.routing.method = requestMethod.toUpperCase();
1443
-
1741
+
1444
1742
  local.res.setHeader('access-control-allow-methods', localRequestMethod);
1445
-
1446
- return localRequestMethod;
1743
+
1744
+ return localRequestMethod;
1447
1745
  }
1448
-
1746
+
1449
1747
  this.getRequestMethod = function() {
1450
1748
  return localRequestMethod;
1451
1749
  }
1452
-
1750
+
1453
1751
  this.setRequestMethodParams = function(params) {
1454
1752
  localRequestMethodParams = local.req[local.req.method.toLowerCase()] = localRequestMethodParams = params
1455
1753
  }
1456
-
1754
+
1457
1755
  this.getRequestMethodParams = function() {
1458
- return (localRequestMethodParams) ? localRequestMethodParams : local.req[local.req.method.toLowerCase()]
1756
+ return (localRequestMethodParams) ? localRequestMethodParams : local.req[local.req.method.toLowerCase()]
1459
1757
  }
1460
-
1758
+
1461
1759
  /**
1462
1760
  * isStaticRoute
1463
1761
  * Trying to determine if url is a `statics` ressource
1464
- *
1762
+ *
1465
1763
  * @param {string} url
1466
1764
  * @param {string} method
1467
- *
1765
+ *
1468
1766
  * @returns {boolean} isStaticRoute
1469
1767
  */
1470
1768
  var isStaticRoute = function(url, method, bundle, env, conf) {
1471
-
1769
+
1472
1770
  if ( !/get/i.test(method) ) {
1473
1771
  return false
1474
1772
  }
1475
-
1773
+
1476
1774
  // priority to statics - this portion of code has been duplicated to Server.js
1477
-
1775
+
1478
1776
  var staticsArr = conf[bundle][env].publicResources;
1479
1777
  var staticProps = {
1480
1778
  firstLevel : '/' + url.split(/\//g)[1] + '/',
1481
1779
  // to be considered as a stativ content, url must content at least 2 caracters after last `.`: .js, .html are ok
1482
1780
  isStaticFilename : /(\.([A-Za-z0-9]+){2}|\/)$/.test(url)
1483
- };
1484
-
1781
+ };
1782
+
1485
1783
  // handle resources from public with webroot in url
1486
1784
  if ( staticProps.isStaticFilename && conf[bundle][env].server.webroot != '/' && staticProps.firstLevel == conf[bundle][env].server.webroot ) {
1487
1785
  var matchedFirstInUrl = url.replace(conf[bundle][env].server.webroot, '').match(/[A-Za-z0-9_-]+\/?/);
1488
1786
  if ( matchedFirstInUrl && matchedFirstInUrl.length > 0 ) {
1489
- staticProps.firstLevel = conf[bundle][env].server.webroot + matchedFirstInUrl[0]
1490
- }
1787
+ staticProps.firstLevel = conf[bundle][env].server.webroot + matchedFirstInUrl[0];
1788
+ }
1789
+ matchedFirstInUrl = null;
1491
1790
  }
1492
-
1493
- if (
1494
- staticProps.isStaticFilename && staticsArr.indexOf(url) > -1
1495
- || staticProps.isStaticFilename && staticsArr.indexOf( url.replace(url.substr(url.lastIndexOf('/')+1), '') ) > -1
1791
+
1792
+ if (
1793
+ staticProps.isStaticFilename && staticsArr.indexOf(url) > -1
1794
+ || staticProps.isStaticFilename && staticsArr.indexOf( url.replace(url.substr(url.lastIndexOf('/')+1), '') ) > -1
1496
1795
  || staticProps.isStaticFilename && staticsArr.indexOf(staticProps.firstLevel) > -1
1497
1796
  ) {
1797
+ staticProps = null;
1498
1798
  return true
1499
1799
  }
1500
-
1800
+ staticProps = null;
1801
+
1501
1802
  return false;
1502
1803
  }
1503
1804
 
1504
1805
  /**
1505
1806
  * redirect
1506
1807
  *
1507
- * TODO - improve redirect based on `utils.routing`
1808
+ * TODO - improve redirect based on `lib.routing`
1508
1809
  * e.g.: self.redirect('project-get', { companyId: companyId, clientId: clientId, id: projectId }, true)
1509
- *
1810
+ *
1510
1811
  * How to avoid redirect inside popin context
1511
1812
  * N.B.: When you are in a popin context, add an `id` to your template tag so it can be ignored by the default PopinHandler
1512
1813
  * E.g.: id="delete-link" -> <a href="#" id="delete-link">delete</a>
1513
1814
  *
1514
- * You have to ways of using this method
1815
+ * You have two ways of using this method
1515
1816
  *
1516
1817
  * 1) Through routing.json
1517
1818
  * ---------------------
@@ -1553,21 +1854,21 @@ function SuperController(options) {
1553
1854
  * `ignoreWebRoot` behaves the like set to `false` by default
1554
1855
  *
1555
1856
  * N.B.: Gina will tell browsers not to cache redirections if you are using `dev` environement
1556
- *
1857
+ *
1557
1858
  * Trobleshouting:
1558
1859
  * ---------------
1559
- *
1860
+ *
1560
1861
  * Redirecting to a popin from the controller while posting from a form
1561
1862
  * If this does not work, like doing a real redirect, this
1562
1863
  * only means that the ID you are using for the form might be
1563
1864
  * a duplicate one from the the main document !!!
1564
1865
  *
1565
- * @param {object|string} req|rule - Request Object or Rule/Route name
1866
+ * @param {object|string} req|rule|url - Request Object or Rule/Route name
1566
1867
  * @param {object|boolean} res|ignoreWebRoot - Response Object or Ignore WebRoot & start from domain root: /
1567
1868
  * @param {object} [params] TODO
1568
1869
  *
1569
1870
  * @callback [ next ]
1570
- * */
1871
+ * */
1571
1872
  this.redirect = function(req, res, next) {
1572
1873
  var conf = self.getConfig();
1573
1874
  var bundle = conf.bundle;
@@ -1579,15 +1880,15 @@ function SuperController(options) {
1579
1880
  var ignoreWebRoot = null, isRelative = false;
1580
1881
  var originalUrl = null;
1581
1882
  var method = null;
1582
- var originalMethod = null;
1883
+ var originalMethod = null;
1583
1884
 
1584
1885
  if ( typeof(req) === 'string' ) {
1585
1886
 
1586
1887
  // if ( typeof(res) == 'undefined') {
1587
1888
  // // nothing to do
1588
1889
  // ignoreWebRoot = false
1589
- // } else
1590
- if (typeof(res) === 'string' || typeof(res) === 'number' || typeof(res) === 'boolean') {
1890
+ // } else
1891
+ if (typeof(res) === 'string' || typeof(res) === 'number' || typeof(res) === 'boolean') {
1591
1892
  if ( /true|1/.test(res) ) {
1592
1893
  ignoreWebRoot = true
1593
1894
  } else if ( /false|0/.test(res) ) {
@@ -1608,26 +1909,26 @@ function SuperController(options) {
1608
1909
  ignoreWebRoot = false;
1609
1910
  }
1610
1911
  }
1611
-
1912
+
1612
1913
  }
1613
1914
 
1614
1915
  if ( req.substr(0,1) === '/') { // is relative (not checking if the URI is defined in the routing.json)
1615
1916
  // if (wroot.substr(wroot.length-1,1) == '/') {
1616
1917
  // wroot = wroot.substr(wroot.length-1,1).replace('/', '')
1617
1918
  // }
1618
-
1919
+
1619
1920
  if ( /^\//.test(req) && !ignoreWebRoot )
1620
1921
  req = req.substr(1);
1621
-
1922
+
1622
1923
  rte = ( ignoreWebRoot != null && ignoreWebRoot ) ? req : wroot + req;
1623
1924
  // cleaning url in case of ?param=value
1624
- originalUrl = rte;
1925
+ originalUrl = rte;
1625
1926
  rte = rte.replace(/\?(.*)/, '');
1626
-
1927
+
1627
1928
  req = local.req;
1628
- originalMethod = ( typeof(req.originalMethod) != 'undefined') ? req.originalMethod : req.method;
1629
- console.debug('[ BUNDLE ][ '+ local.options.conf.bundle +' ][ Controller ] trying to get route: ', rte, bundle, req.method);
1630
- if ( !ignoreWebRoot || !isStaticRoute(rte, req.method, bundle, env, ctx.config.envConf) && !ignoreWebRoot ) {
1929
+ originalMethod = ( typeof(req.originalMethod) != 'undefined') ? req.originalMethod : req.method;
1930
+ console.debug('[ BUNDLE ][ '+ local.options.conf.bundle +' ][ Controller ] trying to get route: ', rte, bundle, req.method);
1931
+ if ( !ignoreWebRoot || !isStaticRoute(rte, req.method, bundle, env, ctx.config.envConf) && !ignoreWebRoot ) {
1631
1932
  req.routing = lib.routing.getRouteByUrl(rte, bundle, req.method, req);
1632
1933
  // try alternative method
1633
1934
  if (!req.routing) {
@@ -1637,7 +1938,7 @@ function SuperController(options) {
1637
1938
  method = req.method = 'GET'
1638
1939
  }
1639
1940
  }
1640
-
1941
+
1641
1942
  //route = route = req.routing.name;
1642
1943
  } else {
1643
1944
  req.routing = {
@@ -1646,59 +1947,59 @@ function SuperController(options) {
1646
1947
  }
1647
1948
  }
1648
1949
  }
1649
-
1950
+
1650
1951
  res = local.res;
1651
1952
  next = local.next;
1652
1953
  isRelative = true;
1653
-
1954
+
1654
1955
  req.routing.param.path = rte
1655
1956
  } else if ( isValidURL(req) ) { // might be an URL
1656
1957
  rte = req;
1657
- originalUrl = rte;
1958
+ originalUrl = rte;
1658
1959
  rte = rte.replace(/\?(.*)/, '');
1659
-
1960
+
1660
1961
  req = local.req;
1661
1962
  res = local.res;
1662
1963
  next = local.next;
1663
-
1964
+
1664
1965
  req.routing.param.url = rte
1665
1966
  } else { // is by default a route name
1666
-
1967
+
1667
1968
  if ( /\@/.test(req) ) {
1668
1969
  var rteArr = req.split(/\//);
1669
1970
  if ( typeof(rteArr[1]) != 'undefined' )
1670
1971
  env = rteArr[1];
1671
-
1972
+
1672
1973
  rte = route = rteArr[0];
1673
1974
  rteArr = rteArr[0].split(/\@/);
1674
-
1975
+
1675
1976
  bundle = rteArr[1];
1676
-
1977
+
1677
1978
  } else {
1678
1979
  rte = route = ( new RegExp('^/'+conf.bundle+'-$').test(req) ) ? req : wroot.match(/[^/]/g).join('') +'-'+ req;
1679
1980
  }
1680
-
1681
-
1981
+
1982
+
1682
1983
  req = local.req;
1683
1984
  res = local.res;
1684
1985
  next = local.next;
1685
-
1986
+
1686
1987
  req.routing.param.route = routing[rte]
1687
- }
1688
-
1988
+ }
1989
+
1689
1990
  } else {
1690
- route = req.routing.param.route;
1991
+ route = req.routing.param.route;
1691
1992
  }
1692
-
1993
+
1693
1994
  if ( !originalMethod ) {
1694
1995
  originalMethod = ( typeof(req.originalMethod) != 'undefined') ? req.originalMethod : req.method;
1695
1996
  }
1696
-
1697
- var path = originalUrl || req.routing.param.path || '';
1997
+
1998
+ var path = originalUrl || req.routing.param.path || '';
1698
1999
  var url = req.routing.param.url;
1699
- var code = req.routing.param.code || 301;
2000
+ var code = req.routing.param.code || 301;
1700
2001
 
1701
- var keepParams = req.routing.param['keep-params'] || false;
2002
+ var keepParams = req.routing.param['keep-params'] || false;
1702
2003
 
1703
2004
  var condition = true; //set by default for url @ path redirect
1704
2005
 
@@ -1710,20 +2011,20 @@ function SuperController(options) {
1710
2011
 
1711
2012
  var isProxyHost = ( typeof(local.req.headers.host) != 'undefined' && local.options.conf.server.scheme +'://'+ local.req.headers.host != local.options.conf.hostname || typeof(local.req.headers[':authority']) != 'undefined' && local.options.conf.server.scheme +'://'+ local.req.headers[':authority'] != local.options.conf.hostname ) ? true : false;
1712
2013
  var hostname = (isProxyHost) ? ctx.config.envConf[bundle][env].hostname.replace(/\:\d+$/, '') : ctx.config.envConf[bundle][env].hostname;
1713
-
2014
+
1714
2015
  // if ( !/\:\d+$/.test(req.headers.host) )
1715
2016
  // hostname = hostname.replace(/\:\d+$/, '');
1716
2017
 
1717
2018
  if (route) { // will go with route first
1718
-
2019
+
1719
2020
  if ( /\,/.test(routing[route].url) ) {
1720
2021
  var paths = routing[route].url.split(/\,/g);
1721
2022
  path = (ignoreWebRoot) ? paths[0].replace(wroot, '') : paths[0];
1722
2023
  } else {
1723
2024
  path = (ignoreWebRoot) ? routing[route].url.replace(wroot, '') : routing[route].url;
1724
2025
  }
1725
-
1726
- if (bundle != conf.bundle) {
2026
+
2027
+ if (bundle != conf.bundle) {
1727
2028
  path = hostname + path;
1728
2029
  }
1729
2030
  } else if (url && !path) {
@@ -1737,87 +2038,123 @@ function SuperController(options) {
1737
2038
  // nothing to do, just ignoring
1738
2039
  //} else {
1739
2040
  } else if ( !path && typeof(isRelative) == 'undefined' ) {
1740
-
2041
+
1741
2042
  path = hostname + path
1742
2043
  //path = local.req.headers.host + path
1743
2044
  }
1744
-
1745
-
1746
2045
 
1747
- if (!local.res.headersSent) {
1748
-
2046
+ var isPopinContext = false;
2047
+ if (
2048
+ typeof(req.routing.param.isPopinContext) != 'undefined'
2049
+ && /^true$/i.test(req.routing.param.isPopinContext)
2050
+ && self.isXMLRequest()
2051
+ ||
2052
+ self.isPopinContext()
2053
+ && self.isXMLRequest()
2054
+ ) {
2055
+ isPopinContext = true;
2056
+ }
2057
+
2058
+ if (!headersSent()) {
2059
+
1749
2060
  // backing up oldParams
1750
2061
  var oldParams = local.req[originalMethod.toLowerCase()];
1751
- var requestParams = req[req.method.toLowerCase()] || {};
2062
+ var requestParams = req[req.method.toLowerCase()] || {};
1752
2063
  if ( typeof(requestParams) != 'undefined' && typeof(requestParams.error) != 'undefined' ) {
1753
2064
  var redirectError = requestParams.error;
1754
2065
  self.throwError(requestParams.error);
1755
2066
  return;
1756
2067
  }
1757
-
1758
- if (
1759
- !/GET/i.test(req.method)
1760
- ||
1761
- originalMethod && !/GET/i.test(originalMethod)
1762
- ) { // trying to redirect using the wrong method ?
1763
-
2068
+
2069
+ if (
2070
+ !/GET/i.test(req.method)
2071
+ ||
2072
+ originalMethod && !/GET/i.test(originalMethod)
2073
+ ) { // trying to redirect using the wrong method ?
2074
+
1764
2075
  console.warn(new Error('Your are trying to redirect using the wrong method: `'+ req.method+'`.\nThis can often occur while redirecting from a controller to another controller or from a bundle to another.\nA redirection is not permitted in this scenario.\nD\'ont panic :)\nSwitching request method to `GET` method instead.\n').message);
1765
2076
  method = local.req.method = self.setRequestMethod('GET', conf);
1766
- code = 303;
2077
+ code = 303;
1767
2078
  }
1768
-
1769
-
2079
+
2080
+ var inheritedDataIsNeeded = ( req.method.toLowerCase() == originalMethod.toLowerCase() ) ? false: true;
2081
+
1770
2082
  // merging new & olds params
1771
2083
  requestParams = merge(requestParams, oldParams);
1772
2084
  // remove session to prevent reaching the 2000 chars limit
1773
2085
  // if you need the session, you need to find another way to retrieve while in the next route
1774
- if ( typeof(requestParams.session) != 'undefined' ) {
2086
+ if ( typeof(requestParams.session) != 'undefined' ) {
1775
2087
  delete requestParams.session;
1776
2088
  }
1777
- if ( typeof(requestParams) != 'undefined' && requestParams.count() > 0 ) {
2089
+ if ( typeof(requestParams) != 'undefined' && requestParams.count() > 0 ) {
1778
2090
  //if ( typeof(requestParams.error) != 'undefined' )
1779
-
2091
+
1780
2092
  var inheritedData = null;
1781
2093
  if ( /\?/.test(path) ) {
1782
- inheritedData = '&inheritedData='+ encodeURIComponent(JSON.stringify(requestParams));
2094
+ inheritedData = '&inheritedData='+ encodeRFC5987ValueChars(JSON.stringify(requestParams));
1783
2095
  } else {
1784
- inheritedData = '?inheritedData='+ encodeURIComponent(JSON.stringify(requestParams));
1785
- }
1786
-
2096
+ inheritedData = '?inheritedData='+ encodeRFC5987ValueChars(JSON.stringify(requestParams));
2097
+ }
2098
+
1787
2099
  if ( inheritedData.length > 2000 ) {
1788
2100
  var error = new ApiError('Controller::redirect(...) exceptions: `inheritedData` reached 2000 chars limit', 424);
1789
2101
  self.throwError(error);
1790
2102
  return;
1791
2103
  }
1792
-
2104
+
1793
2105
  // if redirecting from a xhrRequest
1794
2106
  if ( self.isXMLRequest() ) {
1795
2107
  // `requestParams` should be stored in the session to avoid passing datas in clear
1796
- var redirectObj = { location: path, isXhrRedirect: true };
2108
+ var redirectObj = { isXhrRedirect: true };
2109
+ if (isPopinContext) {
2110
+ redirectObj.popin = {
2111
+ url: path
2112
+ }
2113
+ } else {
2114
+ redirectObj.location = path;
2115
+ }
1797
2116
  if (requestParams.count() > 0) {
1798
2117
  var userSession = req.session.user || req.session;
1799
2118
  if ( userSession && local.haltedRequestUrlResumed ) {
1800
2119
  // will be reused for server.js on `case : 'GET'`
1801
2120
  userSession.inheritedData = requestParams;
1802
2121
  } else { // will be passed in clear
1803
- redirectObj.location += inheritedData;
2122
+ if (isPopinContext) {
2123
+ redirectObj.popin.url += inheritedData
2124
+ } else {
2125
+ redirectObj.location += inheritedData;
2126
+ }
1804
2127
  }
1805
2128
  }
1806
-
2129
+
1807
2130
  self.renderJSON(redirectObj);
1808
2131
  return;
1809
2132
  }
1810
-
1811
- path += inheritedData;
1812
- }
1813
-
2133
+
2134
+ if (inheritedDataIsNeeded) {
2135
+ path += inheritedData;
2136
+ }
2137
+ }
2138
+ // Popin redirect
2139
+ if ( isPopinContext ) {
2140
+ return self.renderJSON({
2141
+ isXhrRedirect: true,
2142
+ popin: {
2143
+ url: path
2144
+ }
2145
+ })
2146
+ }
2147
+
1814
2148
  var ext = 'html';
1815
2149
  res.setHeader('content-type', local.options.conf.server.coreConfiguration.mime[ext]);
1816
-
1817
- if (
1818
- typeof(local.res._headers) != 'undefined'
1819
- && typeof(local.res._headers['access-control-allow-methods']) != 'undefined'
1820
- && local.res._headers['access-control-allow-methods'] != req.method
2150
+
2151
+ var resHeaderACAM = res.getHeader('access-control-allow-methods');
2152
+ if (
2153
+ // typeof(local.res._headers) != 'undefined'
2154
+ // && typeof(local.res._headers['access-control-allow-methods']) != 'undefined'
2155
+ // && local.res._headers['access-control-allow-methods'] != req.method
2156
+ typeof(resHeaderACAM) != 'undefined'
2157
+ && resHeaderACAM != req.method
1821
2158
  ||
1822
2159
  !new RegExp(req.method, 'i').test( res.getHeader('access-control-allow-methods') )
1823
2160
  ) {
@@ -1825,11 +2162,11 @@ function SuperController(options) {
1825
2162
  }
1826
2163
  //path += '?query='+ JSON.stringify(self.getRequestMethodParams());
1827
2164
  local.req[req.method.toLowerCase()] = self.getRequestMethodParams() || {};
1828
-
2165
+
1829
2166
  var headInfos = {
1830
- 'location': path
1831
- };
1832
-
2167
+ 'location': path
2168
+ };
2169
+
1833
2170
  if (self.isCacheless()) {
1834
2171
  res.writeHead(code, merge(headInfos, {
1835
2172
  'cache-control': 'no-cache, no-store, must-revalidate', // preventing browsers from using cache
@@ -1838,24 +2175,26 @@ function SuperController(options) {
1838
2175
  }))
1839
2176
  } else {
1840
2177
  res.writeHead(code, headInfos)
1841
- }
1842
- // in case of query from another bundle waiting for a response
1843
- var redirectObject = JSON.stringify({ status: code, headers: headInfos });
1844
- res.end(redirectObject);
2178
+ }
2179
+ // in case of query from another bundle waiting for a response
2180
+ var redirectObject = JSON.stringify({ status: code, headers: headInfos });
2181
+
1845
2182
  try {
2183
+ res.end(redirectObject);
1846
2184
  local.res.headersSent = true;// done for the render() method
1847
2185
  } catch(err){
1848
2186
  // ignoring the warning
2187
+ // console.warn(err.stack);
1849
2188
  }
1850
-
2189
+
1851
2190
  console.info(local.req.method.toUpperCase() +' ['+code+'] '+ path);
1852
-
2191
+
1853
2192
  if ( typeof(next) != 'undefined' )
1854
2193
  next();
1855
2194
  else
1856
2195
  return;
1857
2196
  }
1858
-
2197
+
1859
2198
  }
1860
2199
  }
1861
2200
 
@@ -1896,16 +2235,19 @@ function SuperController(options) {
1896
2235
  })
1897
2236
  }
1898
2237
  }
1899
-
2238
+
1900
2239
  this.getBundleStatus = function(req, res, next) {
2240
+ var conf = self.getConfig();
1901
2241
  self.renderJSON({
1902
2242
  status: 200,
1903
2243
  isAlive: true,
1904
- message: 'I am alive !'
2244
+ message: 'I am alive !',
2245
+ // bundle: conf.bundle,
2246
+ // project: conf.projectName
1905
2247
  });
1906
2248
  }
1907
-
1908
- this.checkBundleStatus = async function(bundle, cb) {
2249
+
2250
+ this.checkBundleStatus = async function(bundle, cb) {
1909
2251
  var opt = self.getConfig('app').proxy[bundle];
1910
2252
  var route = lib.routing.getRoute('bundle-status@'+bundle);
1911
2253
  opt.method = 'GET';
@@ -1915,29 +2257,35 @@ function SuperController(options) {
1915
2257
  .then( function onQueryResponse(_status) {
1916
2258
  response = _status
1917
2259
  });
1918
-
2260
+
1919
2261
  if (cb) {
1920
2262
  cb(error, response);
1921
2263
  } else {
1922
2264
  return response;
1923
2265
  }
1924
2266
  }
1925
-
2267
+
1926
2268
  /**
1927
2269
  * downloadFromURL
1928
2270
  * Download from an URL
1929
2271
  * - attachment/inline
1930
2272
  * OR
1931
- * - locally: `Controller.store(target, cb)` must be called to store on `onComplete` event
1932
- *
2273
+ * - locally: `Controller.store(target, cb)` must be called to store on `onComplete` event
2274
+ *
2275
+ * - Will trigger on frontend : Failed to load resource: Frame load interrupted
2276
+ * because there is no `res.end()`: whitch is normal, we want to stay on the referrer page
2277
+ *
2278
+ * - To avoid this, add to your download link the attribute `data-gina-link`
2279
+ * This will convert the regular HTTP Request to an XML Request
2280
+ *
1933
2281
  * @param {string} url - eg.: https://upload.wikimedia.org/wikipedia/fr/2/2f/Firefox_Old_Logo.png
1934
2282
  * @param {object} [options]
1935
- *
1936
- *
2283
+ *
2284
+ *
1937
2285
  * */
1938
2286
  this.downloadFromURL = function(url, options) {
1939
-
1940
- var defaultOptions = {
2287
+
2288
+ var defaultOptions = {
1941
2289
  // file name i you want to rename the file
1942
2290
  file: null,
1943
2291
  fileSize: null,
@@ -1947,7 +2295,7 @@ function SuperController(options) {
1947
2295
  contentDisposition: 'attachment',
1948
2296
  // content-type (https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Configuring_server_MIME_types)
1949
2297
  contentType: 'application/octet-stream',
1950
-
2298
+
1951
2299
  agent: false,
1952
2300
  // set to false to ignore certificate verification
1953
2301
  rejectUnauthorized: true,
@@ -1957,9 +2305,9 @@ function SuperController(options) {
1957
2305
  keepAlive: true,
1958
2306
  headers: {}
1959
2307
  };
1960
-
2308
+
1961
2309
  var opt = ( typeof(options) != 'undefined' ) ? merge(options, defaultOptions) : defaultOptions;
1962
-
2310
+
1963
2311
  var requestOptions = {};
1964
2312
  for (var o in opt) {
1965
2313
  if ( !/(toLocalDir|contentDisposition|contentType|file)/.test(o) )
@@ -1968,130 +2316,135 @@ function SuperController(options) {
1968
2316
 
1969
2317
  // defining protocol & scheme
1970
2318
  var protocol = null;
1971
- var scheme = null;
1972
-
2319
+ var scheme = null;
2320
+
1973
2321
  if ( /\:\/\//.test(url) ) {
1974
2322
  scheme = url.match(/^\w+\:/)[0];
1975
2323
  scheme = scheme.substr(0, scheme.length-1);
1976
-
2324
+
1977
2325
  if ( !/^http/.test(scheme) ) {
1978
2326
  self.throwError(local.res, 500, new Error('[ '+ scheme +' ] Scheme not supported. Ref.: `http` or `https` only'));
1979
2327
  return;
1980
2328
  }
1981
-
1982
-
1983
-
2329
+
2330
+
2331
+
1984
2332
  } else { // by default
1985
2333
  scheme = 'http';
1986
2334
  }
1987
-
2335
+
1988
2336
  requestOptions.scheme = scheme +':';
1989
-
2337
+
1990
2338
  //defining port
1991
2339
  var port = url.match(/\:\d+\//) || null;
1992
2340
  if ( port != null ) {
1993
2341
  port = port[0].substr(1, port[0].length-2);
1994
- requestOptions.port = ~~port;
2342
+ requestOptions.port = ~~port;
1995
2343
  }
1996
-
2344
+
1997
2345
  // defining hostname & path
1998
2346
  var parts = url.replace(new RegExp( scheme + '\:\/\/'), '').split(/\//g);
1999
2347
  requestOptions.host = parts[0].replace(/\:\d+/, '');
2000
2348
  requestOptions.path = '/' + parts.splice(1).join('/');
2001
-
2002
-
2349
+
2350
+
2003
2351
  // extension and mime
2004
- var filename = url.split(/\//g).pop();
2352
+ var filename = url.split(/\//g).pop();
2005
2353
  if (!filename) {
2006
2354
  self.throwError(local.res, 500, new Error('Filename not found in url: `'+ url +'`'));
2007
2355
  return;
2008
2356
  }
2009
-
2010
-
2357
+
2358
+
2011
2359
  if ( !/\.\w+$/.test(filename) ) {
2012
2360
  self.throwError(local.res, 500, new Error('[ '+ filename +' ] extension not found.'));
2013
2361
  return;
2014
2362
  }
2015
-
2016
-
2363
+
2364
+
2017
2365
  // filename renaming
2018
2366
  if (opt.file)
2019
2367
  filename = opt.file;
2020
-
2368
+
2021
2369
  if ( opt.contentDisposition == 'attachment') {
2022
2370
  opt.contentDisposition += '; filename=' + filename;
2023
2371
  }
2024
-
2372
+
2025
2373
  var ext = filename.match(/\.\w+$/)[0].substr(1)
2026
2374
  , contentType = null
2027
2375
  , tmp = _(GINA_TMPDIR +'/'+ filename, true)
2028
2376
  ;
2029
-
2377
+
2030
2378
  if ( typeof(local.options.conf.server.coreConfiguration.mime[ext]) != 'undefined' ) {
2031
2379
 
2032
2380
  contentType = (opt.contentType != defaultOptions.contentType) ? opt.contentType : local.options.conf.server.coreConfiguration.mime[ext];
2033
-
2381
+
2034
2382
  } else { // extension not supported
2035
2383
  self.throwError(local.res, 500, new Error('[ '+ ext +' ] Extension not supported. Ref.: gina/core mime.types'));
2036
2384
  return;
2037
2385
  }
2038
-
2386
+
2039
2387
  // defining responseType
2040
2388
  requestOptions.headers['content-type'] = contentType;
2041
2389
  requestOptions.headers['content-disposition'] = opt.contentDisposition;
2042
-
2390
+
2043
2391
  var browser = require(''+ scheme);
2044
2392
  //console.debug('requestOptions: \n', JSON.stringify(requestOptions, null, 4));
2045
-
2046
- browser.get(requestOptions, function(response) {
2047
-
2048
- local.res.setHeader('content-type', contentType + '; charset='+ local.options.conf.encoding);
2049
- local.res.setHeader('content-disposition', opt.contentDisposition);
2050
- if (opt.fileSize) {
2051
- local.res.setHeader('content-length', opt.fileSize);
2052
- }
2053
- //local.res.setHeader('content-length', opt.fileSize);
2054
- // local.res.setHeader('cache-control', 'must-revalidate');
2055
- // local.res.setHeader('pragma', 'must-revalidate');
2056
-
2057
- // response.on('end', function onResponsePipeEnd(){
2058
- // self.renderJSON({ url: url});
2059
- // //local.res.end( Buffer.from(data) );
2060
- // //local.res.headersSent = true;
2061
-
2062
- // // if ( typeof(local.next) != 'undefined')
2063
- // // local.next();
2064
- // // else
2065
- // // return;
2066
- // });
2067
-
2068
- response.pipe(local.res);
2069
- });
2070
-
2071
- return;
2072
2393
 
2394
+ browser
2395
+ .get(requestOptions, function(response) {
2396
+
2397
+ local.res.setHeader('content-type', contentType + '; charset='+ local.options.conf.encoding);
2398
+ local.res.setHeader('content-disposition', opt.contentDisposition);
2399
+ if (opt.fileSize) {
2400
+ local.res.setHeader('content-length', opt.fileSize);
2401
+ }
2402
+ //local.res.setHeader('content-length', opt.fileSize);
2403
+ // local.res.setHeader('cache-control', 'must-revalidate');
2404
+ // local.res.setHeader('pragma', 'must-revalidate');
2405
+
2406
+
2407
+ response.pipe(local.res);
2408
+ })
2409
+ .on('error', function onDownloadError(err) {
2410
+ self.throwError(local.res, 500, err);
2411
+ });
2412
+
2413
+
2414
+
2415
+ // Will trigger on frontend : Failed to load resource: Frame load interrupted
2416
+ // because there is no `res.end()`: whitch is normal, we want to stay on the referrer page
2417
+
2418
+ // To avoid this, add to your download link the attribute `data-gina-link`
2419
+ // This will convert the regular HTTP Request to an XML Request
2073
2420
  }
2074
2421
 
2075
-
2422
+
2076
2423
  /**
2077
2424
  * Download to targeted filename.ext - Will create target if new
2078
2425
  * Use `cb` callback or `onComplete` event
2079
2426
  *
2427
+ * - Will trigger on frontend : Failed to load resource: Frame load interrupted
2428
+ * because there is no `res.end()`: whitch is normal, we want to stay on the referrer page
2429
+ *
2430
+ * - To avoid this, add to your download link the attribute `data-gina-link`
2431
+ * This will convert the regular HTTP Request to an XML Request
2432
+ *
2080
2433
  * @param {string} filename
2081
2434
  * @param {object} options
2082
2435
  **/
2083
2436
  this.downloadFromLocal = function(filename) {
2084
-
2085
- var file = filename.split(/\//g).pop();
2437
+
2438
+ var file = filename.split(/\//g).pop();
2086
2439
  var ext = file.split(/\./g).pop()
2087
2440
  , contentType = null
2088
2441
  ;
2089
-
2442
+
2090
2443
  if ( typeof(local.options.conf.server.coreConfiguration.mime[ext]) != 'undefined' ) {
2091
2444
 
2092
2445
  contentType = local.options.conf.server.coreConfiguration.mime[ext];
2093
2446
  local.res.setHeader('content-type', contentType);
2094
- local.res.setHeader('content-disposition', 'attachment; filename=' + file);
2447
+ local.res.setHeader('content-disposition', 'attachment; filename=' + file);
2095
2448
 
2096
2449
  var filestream = fs.createReadStream(filename);
2097
2450
  filestream.pipe(local.res);
@@ -2099,7 +2452,7 @@ function SuperController(options) {
2099
2452
  } else { // extension not supported
2100
2453
  self.throwError(local.res, 500, new Error('[ '+ ext +' ] Extension not supported. Ref.: gina/core mime.types'));
2101
2454
  return;
2102
- }
2455
+ }
2103
2456
  }
2104
2457
 
2105
2458
 
@@ -2122,17 +2475,17 @@ function SuperController(options) {
2122
2475
  * */
2123
2476
  this.store = async function(target, files, cb) {
2124
2477
 
2125
-
2478
+
2126
2479
  var start = function(target, files, cb) {
2127
-
2480
+
2128
2481
  if (arguments.length == 2 && typeof(arguments[1]) == 'function' ) {
2129
2482
  var cb = arguments[1];
2130
2483
  }
2131
-
2484
+
2132
2485
  if ( typeof(files) == 'undefined' || typeof(files) == 'function' ) {
2133
2486
  files = local.req.files
2134
2487
  }
2135
-
2488
+
2136
2489
  var uploadedFiles = [];
2137
2490
 
2138
2491
  if ( typeof(files) == 'undefined' || files.count() == 0 ) {
@@ -2155,25 +2508,25 @@ function SuperController(options) {
2155
2508
  self.emit('uploaded', folder)
2156
2509
  }
2157
2510
  } else {
2158
- // files list
2159
- var fileName = null;
2511
+ // files list
2512
+ var fileName = null;
2160
2513
  for (var len = files.length; i < len; ++i ){
2161
-
2162
- fileName = files[i].filename || files[i].originalFilename
2163
-
2514
+
2515
+ fileName = files[i].filename || files[i].originalFilename
2516
+
2164
2517
  list[i] = {
2165
2518
  source: files[i].path,
2166
2519
  target: _(uploadDir.toString() + '/' + fileName)
2167
2520
  };
2168
-
2169
- uploadedFiles[i] = {
2521
+
2522
+ uploadedFiles[i] = {
2170
2523
  file : fileName,
2171
- filename : list[i].target,
2524
+ filename : list[i].target,
2172
2525
  size : files[i].size,
2173
2526
  type : files[i].type,
2174
2527
  encoding : files[i].encoding
2175
2528
  };
2176
-
2529
+
2177
2530
  }
2178
2531
 
2179
2532
  movefiles(0, local.res, list, function (err) {
@@ -2279,7 +2632,7 @@ function SuperController(options) {
2279
2632
  } while (cert.fingerprint256 !== lastprint256);
2280
2633
 
2281
2634
  }*/
2282
-
2635
+
2283
2636
  };
2284
2637
 
2285
2638
  this.query = function() { // options, data, callback
@@ -2293,7 +2646,7 @@ function SuperController(options) {
2293
2646
  data = arguments[arguments.length-1]
2294
2647
  }
2295
2648
  // preventing multiple call of self.query() when controller is rendering from another required controller
2296
- if (
2649
+ if (
2297
2650
  typeof(local.options) != 'undefined'
2298
2651
  && typeof(local.options.renderingStack) != 'undefined'
2299
2652
  && local.options.renderingStack.length > 1
@@ -2301,22 +2654,23 @@ function SuperController(options) {
2301
2654
  return false
2302
2655
  }
2303
2656
  self.isProcessingError = false; // by default
2304
-
2657
+
2305
2658
  var queryData = {}
2306
2659
  , defaultOptions = local.query.options
2307
2660
  , path = options.path
2308
- , browser = null
2661
+ , browser = null
2309
2662
  ;
2310
2663
 
2311
2664
  // options must be used as a copy in case of multiple calls of self.query(options, ...)
2312
2665
  options = merge(JSON.clone(options), defaultOptions);
2313
-
2666
+ // options = merge(options, defaultOptions);
2667
+
2314
2668
  for (var o in options) {//cleaning
2315
2669
  if ( typeof(options[o]) == 'undefined' || options[o] == undefined) {
2316
2670
  delete options[o]
2317
2671
  }
2318
2672
  }
2319
-
2673
+
2320
2674
  if (self.isCacheless() || self.isLocalScope() ) {
2321
2675
  options.rejectUnauthorized = false;
2322
2676
  }
@@ -2329,23 +2683,14 @@ function SuperController(options) {
2329
2683
  self.emit('query#complete', err)
2330
2684
  }
2331
2685
 
2332
-
2333
2686
 
2334
- // if (arguments.length <3) {
2335
- // if ( typeof(data) == 'function') {
2336
- // var callback = data;
2337
- // var data = undefined;
2338
- // } else {
2339
- // callback = undefined;
2340
- // }
2341
- // }
2342
2687
  if ( typeof(data) != 'undefined' && data.count() > 0) {
2343
2688
 
2344
2689
  queryData = '?';
2345
2690
  // TODO - if 'application/json' && method == (put|post)
2346
2691
  if ( ['put', 'post'].indexOf(options.method.toLowerCase()) >-1 && /(text\/plain|application\/json|application\/x\-www\-form)/i.test(options.headers['content-type']) ) {
2347
2692
  // replacing
2348
- queryData = encodeURIComponent(JSON.stringify(data))
2693
+ queryData = encodeRFC5987ValueChars(JSON.stringify(data))
2349
2694
  //queryData = JSON.stringify(data)
2350
2695
 
2351
2696
  } else {
@@ -2357,12 +2702,12 @@ function SuperController(options) {
2357
2702
  if ( typeof(tmpData[d]) == 'object') {
2358
2703
  tmpData[d] = JSON.stringify(tmpData[d]);
2359
2704
  }
2360
- queryData += d + '=' + encodeURIComponent(tmpData[d]) + '&';
2705
+ queryData += d + '=' + encodeRFC5987ValueChars(tmpData[d]) + '&';
2361
2706
  }
2362
2707
 
2363
2708
  queryData = queryData.substring(0, queryData.length-1);
2364
2709
  queryData = queryData.replace(/\s/g, '%20');
2365
-
2710
+
2366
2711
  options.path += queryData;
2367
2712
  }
2368
2713
 
@@ -2370,7 +2715,7 @@ function SuperController(options) {
2370
2715
  queryData = ''
2371
2716
  }
2372
2717
 
2373
-
2718
+
2374
2719
  // Internet Explorer override
2375
2720
  if ( local.req != null && /msie/i.test(local.req.headers['user-agent']) ) {
2376
2721
  options.headers['content-type'] = 'text/plain';
@@ -2389,7 +2734,7 @@ function SuperController(options) {
2389
2734
 
2390
2735
  //you need this, even when empty.
2391
2736
  options.headers['content-length'] = queryData.length;
2392
-
2737
+
2393
2738
  // adding gina headers
2394
2739
  if ( local.req != null && typeof(local.req.ginaHeaders) != 'undefined' ) {
2395
2740
  // gina form headers
@@ -2405,7 +2750,7 @@ function SuperController(options) {
2405
2750
  ;
2406
2751
  // cleanup options.path
2407
2752
  if (/\:\/\//.test(options.path)) {
2408
-
2753
+
2409
2754
  var hArr = options.path.split(/^(https|http)\:\/\//);
2410
2755
  var domain = hArr[1] +'://';
2411
2756
  var host = hArr[2].split(/\//)[0];
@@ -2417,72 +2762,84 @@ function SuperController(options) {
2417
2762
  .replace(options.host, '')
2418
2763
  .replace(':'+port, '');
2419
2764
  }
2420
-
2765
+
2421
2766
  // retrieve protocol & scheme: if empty, take the bundles protocol
2422
2767
  protocol = options.protocol || ctx.gina.config.envConf[ctx.bundle][ctx.env].server.protocol;// bundle servers's protocol by default
2423
2768
  protocol = protocol.match(/[.a-z 0-9]+/ig)[0];
2424
2769
  scheme = options.scheme || ctx.gina.config.envConf[ctx.bundle][ctx.env].server.scheme;// bundle servers's scheme by default
2425
2770
  scheme = scheme.match(/[a-z 0-9]+/ig)[0];
2426
-
2771
+ // retrieve credentials
2772
+ if ( typeof(options.ca) == 'undefined' || ! options.ca ) {
2773
+ options.ca = ctx.gina.config.envConf[ctx.bundle][ctx.env].server.credentials.ca;
2774
+ }
2775
+
2427
2776
  //retrieving dynamic host, hostname & port
2428
2777
  if ( /\@/.test(options.hostname) ) {
2429
-
2778
+
2430
2779
  var bundle = ( options.hostname.replace(/(.*)\:\/\//, '') ).split(/\@/)[0];
2431
-
2780
+
2432
2781
  // No shorcut possible because conf.hostname might differ from user inputs
2433
2782
  options.host = ctx.gina.config.envConf[bundle][ctx.env].host.replace(/(.*)\:\/\//, '').replace(/\:\d+/, '');
2434
2783
  options.hostname = ctx.gina.config.envConf[bundle][ctx.env].hostname;
2435
2784
  options.port = ctx.gina.config.envConf[bundle][ctx.env].server.port;
2436
-
2785
+
2437
2786
  options.protocol = ctx.gina.config.envConf[bundle][ctx.env].server.protocol;
2438
2787
  options.scheme = ctx.gina.config.envConf[bundle][ctx.env].server.scheme;
2788
+
2789
+ // retrieve credentials
2790
+ if ( typeof(options.ca) == 'undefined' || ! options.ca ) {
2791
+ options.ca = ctx.gina.config.envConf[bundle][ctx.env].server.credentials.ca;
2792
+ }
2793
+
2439
2794
  // might be != from the bundle requesting
2440
- //options.protocol = ctx.gina.config.envConf[bundle][ctx.env].content.settings.server.protocol || ctx.gina.config.envConf[bundle][ctx.env].server.protocol;
2441
- //options.scheme = ctx.gina.config.envConf[bundle][ctx.env].content.settings.server.scheme || ctx.gina.config.envConf[bundle][ctx.env].server.scheme;
2795
+ //options.protocol = ctx.gina.config.envConf[bundle][ctx.env].content.settings.server.protocol || ctx.gina.config.envConf[bundle][ctx.env].server.protocol;
2796
+ //options.scheme = ctx.gina.config.envConf[bundle][ctx.env].content.settings.server.scheme || ctx.gina.config.envConf[bundle][ctx.env].server.scheme;
2442
2797
  }
2443
-
2798
+
2444
2799
  if ( typeof(options.protocol) == 'undefined' ) {
2445
2800
  options.protocol = protocol
2446
2801
  }
2447
2802
  if ( typeof(options.scheme) == 'undefined' ) {
2448
2803
  options.scheme = scheme
2449
2804
  }
2450
-
2451
-
2805
+
2806
+
2807
+
2808
+
2452
2809
  // reformating scheme
2453
2810
  if( !/\:$/.test(options.scheme) )
2454
2811
  options.scheme += ':';
2455
-
2456
- try {
2457
- options.queryData = queryData;
2812
+
2813
+ try {
2814
+ options.queryData = queryData;
2458
2815
  var protocolVersion = ~~options.protocol.match(/\/(.*)$/)[1].replace(/\.\d+/, '');
2459
2816
  var httpLib = options.protocol.match(/^(.*)\//)[1] + ( (protocolVersion >= 2) ? protocolVersion : '' );
2460
2817
  if ( !/http2/.test(httpLib) && /https/.test(options.scheme) ) {
2461
2818
  httpLib += 's';
2462
2819
  }
2463
-
2464
- browser = require(''+ httpLib);
2465
-
2820
+
2821
+ browser = require(''+ httpLib);
2822
+
2466
2823
  if ( /http2/.test(httpLib) ) {
2467
2824
  return handleHTTP2ClientRequest(browser, options, callback);
2468
2825
  } else {
2469
- return handleHTTP1ClientRequest(browser, options, callback);
2470
- }
2471
-
2472
-
2826
+ return handleHTTP1ClientRequest(browser, options, callback);
2827
+ }
2828
+
2829
+
2473
2830
  } catch(err) {
2474
2831
  if (callback) {
2475
2832
  return callback(err)
2476
2833
  }
2477
2834
  self.emit('query#complete', err)
2478
2835
  }
2479
-
2836
+
2480
2837
  }
2481
-
2838
+
2482
2839
  var handleHTTP1ClientRequest = function(browser, options, callback) {
2483
-
2840
+
2484
2841
  var altOpt = JSON.clone(options);
2485
-
2842
+
2486
2843
  altOpt.protocol = options.scheme;
2487
2844
  altOpt.hostname = options.host;
2488
2845
  altOpt.port = options.port;
@@ -2492,24 +2849,24 @@ function SuperController(options) {
2492
2849
  } catch(err) {
2493
2850
  self.emit('query#complete', err);
2494
2851
  }
2495
-
2852
+
2496
2853
  } else {
2497
2854
  console.warn('[ CONTROLLER ][ HTTP/1.0#query ] options.encKey not found !');
2498
2855
  }
2499
-
2856
+
2500
2857
  if ( typeof(altOpt.encCert) != 'undefined' ) {
2501
2858
  try {
2502
2859
  altOpt.encCert = fs.readFileSync(options.encCert);
2503
2860
  } catch(err) {
2504
2861
  self.emit('query#complete', err);
2505
2862
  }
2506
-
2863
+
2507
2864
  } else {
2508
2865
  console.warn('[ CONTROLLER ][ HTTP/1.0#query ] options.encCert not found !');
2509
2866
  }
2510
-
2867
+
2511
2868
  altOpt.agent = new browser.Agent(altOpt);
2512
-
2869
+
2513
2870
  var req = browser.request(altOpt, function(res) {
2514
2871
 
2515
2872
  res.setEncoding('utf8');
@@ -2526,24 +2883,24 @@ function SuperController(options) {
2526
2883
  });
2527
2884
 
2528
2885
  res.on('end', function onEnd(err) {
2529
-
2530
-
2886
+
2887
+
2531
2888
  // exceptions filter
2532
2889
  if ( typeof(data) == 'string' && /^Unknown ALPN Protocol/.test(data) ) {
2533
2890
  err = {
2534
2891
  status: 500,
2535
2892
  error: new Error(data)
2536
2893
  };
2537
-
2894
+
2538
2895
  if ( typeof(callback) != 'undefined' ) {
2539
2896
  callback(err)
2540
2897
  } else {
2541
2898
  self.emit('query#complete', err)
2542
2899
  }
2543
-
2900
+
2544
2901
  return
2545
2902
  }
2546
-
2903
+
2547
2904
  //Only when needed.
2548
2905
  if ( typeof(callback) != 'undefined' ) {
2549
2906
  if ( typeof(data) == 'string' && /^(\{|%7B|\[{)|\[\]/.test(data) ) {
@@ -2573,7 +2930,7 @@ function SuperController(options) {
2573
2930
  exception.status = 500;
2574
2931
  self.throwError(exception);
2575
2932
  return;
2576
- }
2933
+ }
2577
2934
 
2578
2935
  } else {
2579
2936
  if ( typeof(data) == 'string' && /^(\{|%7B|\[{)|\[\]/.test(data) ) {
@@ -2600,14 +2957,14 @@ function SuperController(options) {
2600
2957
 
2601
2958
  //starting from from >0.10.15
2602
2959
  req.on('error', function onError(err) {
2603
-
2604
-
2960
+
2961
+
2605
2962
  if (
2606
- typeof(err.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(err.code)
2607
- || typeof(err.cause) != 'undefined' && typeof(err.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(err.cause.code)
2963
+ typeof(err.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(err.code)
2964
+ || typeof(err.cause) != 'undefined' && typeof(err.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(err.cause.code)
2608
2965
  ) {
2609
2966
 
2610
- var port = getContext('gina').ports[options.protocol][options.scheme.replace(/\:/, '')][ options.port ];//err.port || err.cause.port
2967
+ var port = getContext('gina').ports[options.protocol][options.scheme.replace(/\:/, '')][ options.port ];//err.port || err.cause.port
2611
2968
  if ( typeof(port) != 'undefined' ) {
2612
2969
  err.accessPoint = port;
2613
2970
  err.message = '`Controller::query()` could not connect to [ ' + err.accessPoint + ' ] using port '+options.port+'.\n';
@@ -2626,7 +2983,7 @@ function SuperController(options) {
2626
2983
  } else {
2627
2984
  var error = {
2628
2985
  status : 500,
2629
- error : err.stack || err.message
2986
+ error : err.stack || err.message
2630
2987
  };
2631
2988
 
2632
2989
  self.emit('query#complete', error)
@@ -2667,30 +3024,28 @@ function SuperController(options) {
2667
3024
  exception.status = 500;
2668
3025
  self.throwError(exception);
2669
3026
  return;
2670
- }
3027
+ }
2671
3028
  })
2672
3029
  }
2673
-
3030
+
2674
3031
  }
2675
3032
  }
2676
-
3033
+
2677
3034
  var handleHTTP2ClientRequest = function(browser, options, callback) {
2678
-
2679
- //cleanup
3035
+
3036
+ //cleanup
2680
3037
  options[':authority'] = options.hostname;
2681
-
2682
- delete options.host;
2683
-
3038
+
2684
3039
  if ( typeof(options[':path']) == 'undefined' ) {
2685
3040
  options[':path'] = options.path;
2686
3041
  delete options.path;
2687
- }
3042
+ }
2688
3043
  if ( typeof(options[':method']) == 'undefined' ) {
2689
3044
  options[':method'] = options.method.toUpperCase();
2690
3045
  delete options.method;
2691
3046
  }
2692
-
2693
- // only if binary !!
3047
+
3048
+ // only if binary !!
2694
3049
  // if ( typeof(options['content-length']) == 'undefined' ) {
2695
3050
  // options['content-length'] = options.headers['content-length'] ;
2696
3051
  // delete options.headers['content-length'];
@@ -2699,11 +3054,24 @@ function SuperController(options) {
2699
3054
  // options['content-type'] = options.headers['content-type'] ;
2700
3055
  // delete options.headers['content-type'];
2701
3056
  // }
2702
-
3057
+
2703
3058
  if ( typeof(options[':scheme']) == 'undefined' ) {
2704
- options[':scheme'] = options.scheme ;
3059
+ options[':scheme'] = options.scheme;
3060
+ }
3061
+
3062
+ if ( typeof(options[':hostname']) == 'undefined' ) {
3063
+ options[':hostname'] = options.hostname;
3064
+ }
3065
+ if (
3066
+ typeof(options[':port']) == 'undefined'
3067
+ && typeof(options.port) != 'undefined'
3068
+ && options.port
3069
+ ) {
3070
+ options[':port'] = options.port;
3071
+ options[':hostname'] = options.host;
2705
3072
  }
2706
-
3073
+ delete options.host;
3074
+
2707
3075
  if ( typeof(options.ca) != 'undefined' ) {
2708
3076
  try {
2709
3077
  options.ca = fs.readFileSync(options.ca);
@@ -2713,58 +3081,58 @@ function SuperController(options) {
2713
3081
  } else {
2714
3082
  self.emit('query#complete', err);
2715
3083
  }
2716
-
3084
+
2717
3085
  return;
2718
3086
  }
2719
-
3087
+
2720
3088
  } else {
2721
3089
  console.warn('[ CONTROLLER ][ HTTP/2.0#query ] options.ca not found !');
2722
3090
  }
2723
-
2724
-
3091
+
3092
+
2725
3093
  var body = Buffer.from(options.queryData);
2726
- options.headers['content-length'] = body.length;
3094
+ options.headers['content-length'] = body.length;
2727
3095
  delete options.queryData;
2728
-
2729
-
2730
-
2731
- const client = browser.connect(options.hostname, options);
2732
-
2733
-
3096
+
3097
+
3098
+
3099
+ const client = browser.connect(options.hostname, options);
3100
+
3101
+
2734
3102
  const {
2735
3103
  HTTP2_HEADER_PROTOCOL,
2736
- HTTP2_HEADER_SCHEME,
3104
+ HTTP2_HEADER_SCHEME,
2737
3105
  HTTP2_HEADER_AUTHORITY,
2738
3106
  HTTP2_HEADER_PATH,
2739
3107
  HTTP2_HEADER_METHOD,
2740
3108
  HTTP2_HEADER_STATUS
2741
3109
  } = browser.constants;
2742
-
2743
-
3110
+
3111
+
2744
3112
  if ( typeof(local.req.headers['x-requested-with']) != 'undefined' ) {
2745
3113
  options.headers['x-requested-with'] = local.req.headers['x-requested-with']
2746
3114
  }
2747
-
3115
+
2748
3116
  if ( typeof(local.req.headers['access-control-allow-credentials']) != 'undefined' ) {
2749
3117
  options.headers['access-control-allow-credentials'] = local.req.headers['access-control-allow-credentials']
2750
3118
  }
2751
-
3119
+
2752
3120
  if ( typeof(local.req.headers['content-type']) != 'undefined' && local.req.headers['content-type'] != options.headers['content-type'] ) {
2753
3121
  options.headers['content-type'] = local.req.headers['content-type']
2754
3122
  }
2755
-
2756
- var headers = merge({
3123
+
3124
+ var headers = merge({
2757
3125
  [HTTP2_HEADER_METHOD]: options[':method'],
2758
- [HTTP2_HEADER_PATH]: options[':path']
3126
+ [HTTP2_HEADER_PATH]: options[':path']
2759
3127
  }, options.headers);
2760
-
3128
+
2761
3129
  // merging with user options
2762
3130
  for (var o in options) {
2763
3131
  if (!/^\:/.test(o) && !/headers/.test(o) && typeof(headers[o]) == 'undefined' ) {
2764
3132
  headers[o] = options[o]
2765
3133
  }
2766
3134
  }
2767
-
3135
+
2768
3136
  /**
2769
3137
  * sessionOptions
2770
3138
  * endStream <boolean> true if the Http2Stream writable side should be closed initially, such as when sending a GET request that should not expect a payload body.
@@ -2778,55 +3146,55 @@ function SuperController(options) {
2778
3146
  endStream = false;
2779
3147
  sessionOptions.endStream = endStream;
2780
3148
  }
2781
-
2782
-
3149
+
3150
+
2783
3151
  client.on('error', (error) => {
2784
-
3152
+
2785
3153
  console.error( '`'+ options[':path']+ '` : '+ error.stack||error.message);
2786
- if (
2787
- typeof(error.cause) != 'undefined' && typeof(error.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(error.cause.code)
2788
- || /ECONNREFUSED|ECONNRESET/.test(error.code)
3154
+ if (
3155
+ typeof(error.cause) != 'undefined' && typeof(error.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(error.cause.code)
3156
+ || /ECONNREFUSED|ECONNRESET/.test(error.code)
2789
3157
  ) {
2790
-
3158
+
2791
3159
  var port = getContext('gina').ports[options.protocol][options.scheme.replace(/\:/, '')][ options.port ];
2792
3160
  if ( typeof(port) != 'undefined' ) {
2793
3161
  error.accessPoint = port;
2794
3162
  error.message = 'Could not connect to [ ' + error.accessPoint + ' ].\nThe `'+port.split(/\@/)[0]+'` bundle is offline or unreachable.\n';
2795
- }
3163
+ }
2796
3164
  }
2797
3165
  self.throwError(error);
2798
3166
  return;
2799
3167
  });
2800
-
3168
+
2801
3169
  client.on('connect', () => {
2802
-
3170
+
2803
3171
  var req = client.request( headers, sessionOptions );
2804
-
2805
-
2806
- // req.on('response', function onQueryResponse(headers, flags) {
3172
+
3173
+
3174
+ // req.on('response', function onQueryResponse(headers, flags) {
2807
3175
  // for (const name in headers) {
2808
3176
  // console.debug(`${name}: ${headers[name]}`);
2809
3177
  // }
2810
3178
  // });
2811
-
3179
+
2812
3180
  req.setEncoding('utf8');
2813
3181
  var data = '';
2814
- req.on('data', function onQueryDataChunk(chunk) {
2815
- data += chunk;
3182
+ req.on('data', function onQueryDataChunk(chunk) {
3183
+ data += chunk;
2816
3184
  });
2817
-
3185
+
2818
3186
  req.on('error', function onQueryError(error) {
2819
3187
 
2820
- if (
2821
- typeof(error.cause) != 'undefined' && typeof(error.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(error.cause.code)
2822
- || /ECONNREFUSED|ECONNRESET/.test(error.code)
3188
+ if (
3189
+ typeof(error.cause) != 'undefined' && typeof(error.cause.code) != 'undefined' && /ECONNREFUSED|ECONNRESET/.test(error.cause.code)
3190
+ || /ECONNREFUSED|ECONNRESET/.test(error.code)
2823
3191
  ) {
2824
-
3192
+
2825
3193
  var port = getContext('gina').ports[options.protocol][options.scheme.replace(/\:/, '')][ options.port ];
2826
3194
  if ( typeof(port) != 'undefined' ) {
2827
3195
  error.accessPoint = port;
2828
3196
  error.message = 'Could not connect to [ ' + error.accessPoint + ' ].\n' + error.message;
2829
- }
3197
+ }
2830
3198
  }
2831
3199
 
2832
3200
 
@@ -2834,7 +3202,7 @@ function SuperController(options) {
2834
3202
  // you can get here if :
2835
3203
  // - you are trying to query using: `enctype="multipart/form-data"`
2836
3204
  // - server responded with an error
2837
- if ( typeof(callback) != 'undefined' ) {
3205
+ if ( typeof(callback) != 'undefined' ) {
2838
3206
  callback(error);
2839
3207
  } else {
2840
3208
  error = {
@@ -2844,28 +3212,28 @@ function SuperController(options) {
2844
3212
 
2845
3213
  self.emit('query#complete', error)
2846
3214
  }
2847
-
3215
+
2848
3216
  return;
2849
3217
  });
2850
-
2851
- req.on('end', function onEnd() {
2852
-
3218
+
3219
+ req.on('end', function onEnd() {
3220
+
2853
3221
  // exceptions filter
2854
3222
  if ( typeof(data) == 'string' && /^Unknown ALPN Protocol/.test(data) ) {
2855
3223
  var err = {
2856
3224
  status: 500,
2857
3225
  error: new Error(data)
2858
3226
  };
2859
-
3227
+
2860
3228
  if ( typeof(callback) != 'undefined' ) {
2861
3229
  callback(err)
2862
3230
  } else {
2863
3231
  self.emit('query#complete', err)
2864
3232
  }
2865
-
3233
+
2866
3234
  return
2867
3235
  }
2868
-
3236
+
2869
3237
  //Only when needed.
2870
3238
  if ( typeof(callback) != 'undefined' ) {
2871
3239
  if ( typeof(data) == 'string' && /^(\{|%7B|\[{)|\[\]/.test(data) ) {
@@ -2896,24 +3264,24 @@ function SuperController(options) {
2896
3264
  if ( data.status && /^3/.test(data.status) && typeof(data.headers) != 'undefined' ) {
2897
3265
  local.res.writeHead(data.status, data.headers);
2898
3266
  return local.res.end();
2899
- }
2900
-
3267
+ }
3268
+
2901
3269
  if ( data.status && !/^2/.test(data.status) && typeof(local.options.conf.server.coreConfiguration.statusCodes[data.status]) != 'undefined' ) {
2902
3270
  if ( /^5/.test(data.status) ) {
2903
- return callback(data)
3271
+ return callback(data)
2904
3272
  } else {
2905
3273
  self.throwError(data);
2906
3274
  return;
2907
- }
3275
+ }
2908
3276
  } else {
2909
3277
  // required when control is used in an halted state
2910
3278
  // Ref.: resumeRequest()
2911
3279
  if ( self && self.isHaltedRequest() && typeof(local.onHaltedRequestResumed) != 'undefined' ) {
2912
3280
  local.onHaltedRequestResumed(false);
2913
3281
  }
2914
- return callback( false, data )
3282
+ return callback( false, data )
2915
3283
  }
2916
-
3284
+
2917
3285
  } catch (e) {
2918
3286
  var infos = local.options, controllerName = infos.controller.substr(infos.controller.lastIndexOf('/'));
2919
3287
  var msg = 'Controller Query Exception while catching back.\nBundle: '+ infos.bundle +'\nController File: /controllers'+ controllerName +'\nControl: this.'+ infos.control +'(...)\n\r' + e.stack;
@@ -2921,8 +3289,8 @@ function SuperController(options) {
2921
3289
  exception.status = 500;
2922
3290
  self.throwError(exception);
2923
3291
  return;
2924
- }
2925
-
3292
+ }
3293
+
2926
3294
  } else {
2927
3295
  if ( typeof(data) == 'string' && /^(\{|%7B|\[{)|\[\]/.test(data) ) {
2928
3296
  try {
@@ -2935,13 +3303,13 @@ function SuperController(options) {
2935
3303
  self.emit('query#complete', data)
2936
3304
  }
2937
3305
  }
2938
-
3306
+
2939
3307
  // intercepting fallback redirect
2940
3308
  if ( data.status && /^3/.test(data.status) && typeof(data.headers) != 'undefined' ) {
2941
3309
  self.removeAllListeners(['query#complete']);
2942
3310
  local.res.writeHead(data.status, data.headers);
2943
3311
  return local.res.end();
2944
- }
3312
+ }
2945
3313
 
2946
3314
  if ( data.status && !/^2/.test(data.status) && typeof(local.options.conf.server.coreConfiguration.statusCodes[data.status]) != 'undefined' ) {
2947
3315
  self.emit('query#complete', data)
@@ -2953,22 +3321,22 @@ function SuperController(options) {
2953
3321
  }
2954
3322
  self.emit('query#complete', false, data)
2955
3323
  }
2956
- }
2957
-
3324
+ }
3325
+
2958
3326
  client.close();
2959
3327
  });
2960
-
3328
+
2961
3329
  if (!endStream) {
2962
3330
  req.end(body);
2963
3331
  }
2964
3332
  });
2965
-
2966
-
3333
+
3334
+
2967
3335
  return {
2968
3336
  onComplete : function(cb) {
2969
-
3337
+
2970
3338
  self.once('query#complete', function(err, data){
2971
-
3339
+
2972
3340
  if ( typeof(data) == 'string' && /^(\{|%7B|\[{)|\[\]/.test(data) ) {
2973
3341
  try {
2974
3342
  data = JSON.parse(data)
@@ -2979,7 +3347,7 @@ function SuperController(options) {
2979
3347
  }
2980
3348
  }
2981
3349
  }
2982
-
3350
+
2983
3351
  try {
2984
3352
  if ( data.status && !/^2/.test(data.status) && typeof(local.options.conf.server.coreConfiguration.statusCodes[data.status]) != 'undefined') {
2985
3353
  cb(data)
@@ -2989,7 +3357,7 @@ function SuperController(options) {
2989
3357
  if ( self.isHaltedRequest() && typeof(local.onHaltedRequestResumed) != 'undefined' ) {
2990
3358
  local.onHaltedRequestResumed(err);
2991
3359
  }
2992
-
3360
+
2993
3361
  cb(err, data)
2994
3362
  }
2995
3363
  } catch (e) {
@@ -2999,7 +3367,7 @@ function SuperController(options) {
2999
3367
  exception.status = 500;
3000
3368
  self.throwError(exception);
3001
3369
  return;
3002
- }
3370
+ }
3003
3371
  })
3004
3372
  }
3005
3373
  }
@@ -3066,8 +3434,8 @@ function SuperController(options) {
3066
3434
  }
3067
3435
 
3068
3436
  req.getParam = function(name) {
3069
-
3070
- var param = null;
3437
+
3438
+ var param = null;
3071
3439
  switch( req.method.toLowerCase() ) {
3072
3440
  case 'get':
3073
3441
  param = req.get[name];
@@ -3089,24 +3457,24 @@ function SuperController(options) {
3089
3457
  return param
3090
3458
  }
3091
3459
  }
3092
-
3460
+
3093
3461
  /**
3094
- * Forward request
3462
+ * Forward request
3095
3463
  * Allowing x-bundle forward
3096
3464
  * Attention: this is a work in progres, do not use it yet
3097
- *
3098
- * @param {object} req
3099
- * @param {object} res
3100
- * @param {callback} next
3101
- * @returns
3465
+ *
3466
+ * @param {object} req
3467
+ * @param {object} res
3468
+ * @param {callback} next
3469
+ * @returns
3102
3470
  */
3103
3471
  this.forward = function(req, res, next) {
3104
3472
  var route = req.routing;
3105
3473
  if ( typeof(route.param.url) == 'undefined' || /^(null|\s*)$/.test(route.param.url) ) {
3106
3474
  self.throwError( new Error('`route.param.url` must be defiend in your route: `'+ route.rule +'`') );
3107
3475
  return;
3108
- }
3109
-
3476
+ }
3477
+
3110
3478
  var param = {};
3111
3479
  for (let p in route.param) {
3112
3480
  if ( /^(url|urlIndex|control|file|title|bundle|project|hostname|port|path|method)$/.test(p) ) {
@@ -3138,14 +3506,14 @@ function SuperController(options) {
3138
3506
  port = route.param.port;
3139
3507
  path = route.param.port;
3140
3508
  }
3141
-
3509
+
3142
3510
  var method = null;
3143
3511
  if ( typeof(route.param.method) != 'undefined' ) {
3144
3512
  method = route.param.method.toLowerCase();
3145
3513
  } else {
3146
3514
  method = req.method.toLowerCase();
3147
3515
  }
3148
-
3516
+
3149
3517
  var opt = {
3150
3518
  ca: ca,
3151
3519
  hostname: hostname,
@@ -3156,7 +3524,7 @@ function SuperController(options) {
3156
3524
  if (self.isCacheless() || self.isLocalScope() ) {
3157
3525
  opt.rejectUnauthorized = false;
3158
3526
  }
3159
-
3527
+
3160
3528
  var obj = req[ req.method.toLowerCase() ];
3161
3529
  // if ( req.files != 'undefined' ) {
3162
3530
  // obj.files = req.files;
@@ -3166,17 +3534,17 @@ function SuperController(options) {
3166
3534
  self.throwError(err);
3167
3535
  return;
3168
3536
  }
3169
-
3537
+
3170
3538
  // TODO - filter : redirect & location
3171
-
3172
- // if ( self.isXMLRequest() || !hasViews() || !local.options.isUsingTemplate && !hasViews() || hasViews() && !local.options.isUsingTemplate ) {
3539
+
3540
+ // if ( self.isXMLRequest() || !hasViews() || !local.options.isUsingTemplate && !hasViews() || hasViews() && !local.options.isUsingTemplate ) {
3173
3541
  self.renderJSON(result)
3174
3542
  // } else {
3175
3543
  // self.render(result)
3176
- // }
3544
+ // }
3177
3545
  });
3178
3546
  }
3179
-
3547
+
3180
3548
 
3181
3549
  /**
3182
3550
  * Get config
@@ -3193,6 +3561,8 @@ function SuperController(options) {
3193
3561
  //config = Object.freeze(local.options.conf.content[name]);
3194
3562
  //Object.seal(local.options.conf.content[name]);
3195
3563
  //Object.freeze(local.options.conf.content[name]);
3564
+ // if ( self.isCacheless() ) {
3565
+ // }
3196
3566
  return JSON.clone(local.options.conf.content[name]);
3197
3567
  } catch (err) {
3198
3568
  return undefined;
@@ -3206,6 +3576,7 @@ function SuperController(options) {
3206
3576
 
3207
3577
  /**
3208
3578
  * Get locales
3579
+ * Will take only supported lang
3209
3580
  *
3210
3581
  * @param {string} [shortCountryCode] - e.g. EN
3211
3582
  *
@@ -3231,29 +3602,27 @@ function SuperController(options) {
3231
3602
  /**
3232
3603
  * Get countries list
3233
3604
  *
3234
- * @param {string} [code] - e.g.: short, long, fifa, m49
3605
+ * @param {string} [code] - e.g.: officialStateName, isoShort, isoLong, continent, capital, currency.name
3235
3606
  *
3236
3607
  * @returns {object} countries - countries code & value list
3237
3608
  * */
3238
3609
  var getCountries = function (code) {
3239
- var list = {}, cde = 'short', name = null;
3610
+ var list = [], cde = 'countryName';
3240
3611
 
3241
3612
  if ( typeof(code) != 'undefined' && typeof(userLocales[0][code]) == 'string' ) {
3242
3613
  cde = code
3243
- } else if ( typeof(code) != 'undefined' ) (
3614
+ } else if ( typeof(code) != 'undefined' ) {
3244
3615
  console.warn('`'+ code +'` not supported : sticking with `short` code')
3245
- )
3246
-
3247
-
3248
- for ( var i = 0, len = userLocales.length; i< len; ++i ) {
3249
-
3250
- if (userLocales[i][cde]) {
3616
+ }
3251
3617
 
3252
- name = userLocales[i].officialName.short || userLocales[i].full;
3253
3618
 
3254
- if ( name )
3255
- list[ userLocales[i][cde] ] = name;
3256
- }
3619
+ for ( let i = 0, len = userLocales.length; i< len; ++i ) {
3620
+ list[ i ] = {
3621
+ isoShort: userLocales[i].isoShort,
3622
+ isoLong: userLocales[i].isoLong,
3623
+ countryName: userLocales[i].countryName,
3624
+ officialStateName: userLocales[i].officialStateName
3625
+ };
3257
3626
  }
3258
3627
 
3259
3628
  return list
@@ -3261,6 +3630,7 @@ function SuperController(options) {
3261
3630
 
3262
3631
  return {
3263
3632
  'getCountries': getCountries
3633
+ // TODO - getCurrencies()
3264
3634
  }
3265
3635
  }
3266
3636
 
@@ -3297,8 +3667,8 @@ function SuperController(options) {
3297
3667
  } else {
3298
3668
  rules = JSON.clone(local.options.conf.content.forms).rules[form.id] || null;
3299
3669
  }
3300
-
3301
- if (!rules) {
3670
+
3671
+ if (!rules) {
3302
3672
  rules = {};
3303
3673
  console.warn('[CONTROLLER]['+ local.options.conf.bundle +'][Backend validation] did not find matching rules for form.id `'+ form.id +'` for `'+ bundle+' bundle`. Do not Panic if you did not defined any.')
3304
3674
  }
@@ -3307,40 +3677,40 @@ function SuperController(options) {
3307
3677
  return;
3308
3678
  }
3309
3679
  }
3310
-
3680
+
3311
3681
  return rules;
3312
3682
  }
3313
-
3683
+
3314
3684
  this.push = function(payload) {
3315
-
3685
+
3316
3686
  var req = local.req, res = local.res;
3317
3687
  var method = req.method.toLowerCase();
3318
3688
  // if no session defined, will push to all active clients
3319
3689
  var sessionId = ( typeof(req[method].sessionID) != 'undefined' ) ? req[method].sessionID : null;
3320
-
3690
+
3321
3691
  // resume current session
3322
-
3323
- if (!payload) {
3324
- payload = null;
3692
+
3693
+ if (!payload) {
3694
+ payload = null;
3325
3695
  if ( typeof(req[method]) != 'undefined' && typeof(req[method].payload) != 'undefined' ) {
3326
3696
  if ( typeof(payload) == 'string' ) {
3327
3697
  payload = decodeURIComponent(req[method].payload)
3328
3698
  } else {
3329
3699
  payload = JSON.stringify(req[method].payload)
3330
- }
3700
+ }
3331
3701
  }
3332
3702
  } else if ( typeof(payload) == 'object' ) {
3333
3703
  payload = JSON.stringify(payload)
3334
- }
3335
-
3704
+ }
3705
+
3336
3706
  try {
3337
3707
  var clients = null;
3338
3708
  if (sessionId) {
3339
3709
  clients = self.serverInstance.eio.getClientsBySessionId(sessionId);
3340
3710
  if (clients)
3341
3711
  clients.send(payload);
3342
- }
3343
-
3712
+ }
3713
+
3344
3714
  // send to all clients if no specific sessionId defined
3345
3715
  if (!sessionId) {
3346
3716
  clients = self.serverInstance.eio.clients;
@@ -3348,14 +3718,14 @@ function SuperController(options) {
3348
3718
  clients[id].send(payload)
3349
3719
  }
3350
3720
  }
3351
-
3721
+
3352
3722
  res.end();
3353
3723
  } catch(err) {
3354
3724
  self.throwError(err);
3355
3725
  return;
3356
- }
3726
+ }
3357
3727
  }
3358
-
3728
+
3359
3729
  var getSession = function() {
3360
3730
  var session = null;
3361
3731
  if ( typeof(local.req.session) != 'undefined') {
@@ -3365,10 +3735,10 @@ function SuperController(options) {
3365
3735
  if (!session && typeof(local.req.session) != 'undefined' && typeof(local.req.session.user) != 'undefined') {
3366
3736
  session = local.req.session.user;
3367
3737
  }
3368
-
3738
+
3369
3739
  return session;
3370
3740
  }
3371
-
3741
+
3372
3742
  this.isHaltedRequest = function(session) {
3373
3743
  // trying to retrieve session since it is optional
3374
3744
  if ( typeof(session) == 'undefined' ) {
@@ -3381,24 +3751,24 @@ function SuperController(options) {
3381
3751
  // session = local.req.session.user;
3382
3752
  // }
3383
3753
  if (
3384
- !session
3385
- ||
3754
+ !session
3755
+ ||
3386
3756
  typeof(session) != 'undefined'
3387
3757
  && typeof(session.haltedRequest) == 'undefined'
3388
3758
  ) {
3389
3759
  return false;
3390
3760
  }
3391
3761
  }
3392
-
3762
+
3393
3763
  return (typeof(session.haltedRequest) != 'undefined' ) ? true : false;
3394
3764
  }
3395
-
3396
-
3765
+
3766
+
3397
3767
  local.haltedRequestUrlResumed = false;
3398
-
3768
+
3399
3769
  this.pauseRequest = function(data, requestStorage) {
3400
-
3401
-
3770
+
3771
+
3402
3772
  // saving halted request
3403
3773
  var req = local.req
3404
3774
  , res = local.res
@@ -3410,22 +3780,22 @@ function SuperController(options) {
3410
3780
  data : JSON.clone(data)
3411
3781
  }
3412
3782
  ;
3413
-
3783
+
3414
3784
  if (
3415
3785
  typeof(requestStorage) == 'undefined'
3416
3786
  && typeof(req.session) != 'undefined'
3417
3787
  ) {
3418
3788
  requestStorage = req.session;
3419
3789
  }
3420
-
3790
+
3421
3791
  if (
3422
- typeof(requestStorage) == 'undefined'
3792
+ typeof(requestStorage) == 'undefined'
3423
3793
  ) {
3424
3794
  var error = new ApiError('`requestStorage` is required', 424);
3425
3795
  self.throwError(error);
3426
3796
  return;
3427
3797
  }
3428
-
3798
+
3429
3799
  var requestParams = {}, i = 0;
3430
3800
  for (var p in req.params) {
3431
3801
  if (i > 0) {
@@ -3436,13 +3806,13 @@ function SuperController(options) {
3436
3806
  if (requestParams.count() > 0) {
3437
3807
  haltedRequest.params = requestParams;
3438
3808
  }
3439
-
3809
+
3440
3810
  requestStorage.haltedRequest = haltedRequest;
3441
-
3811
+
3442
3812
  return requestStorage;
3443
3813
  }
3444
-
3445
-
3814
+
3815
+
3446
3816
  /**
3447
3817
  * resumeRequest
3448
3818
  * Used to resume an halted request
@@ -3450,35 +3820,35 @@ function SuperController(options) {
3450
3820
  * - a middleware attached `haltedRequest` to userSession
3451
3821
  * OR
3452
3822
  * - a persistant object where `haltedRequest` is attached
3453
- *
3454
- * @param {object} req
3455
- * @param {object} res
3823
+ *
3824
+ * @param {object} req
3825
+ * @param {object} res
3456
3826
  * @param {callback|null} next
3457
3827
  * @param {object} [requestStorage] - Will try to use sessionStorage if not passed
3458
3828
  */
3459
3829
  this.resumeRequest = function(requestStorage) {
3460
-
3830
+
3461
3831
  if (local.haltedRequestUrlResumed)
3462
3832
  return;
3463
-
3833
+
3464
3834
  var haltedRequest = null
3465
3835
  , req = local.req
3466
3836
  , res = local.res
3467
3837
  , next = local.next
3468
3838
  ;
3469
-
3839
+
3470
3840
  if (
3471
3841
  typeof(requestStorage) == 'undefined'
3472
3842
  && typeof(req.session) != 'undefined'
3473
3843
  ) {
3474
3844
  requestStorage = req.session;
3475
3845
  }
3476
-
3846
+
3477
3847
  if (
3478
- typeof(requestStorage) == 'undefined'
3848
+ typeof(requestStorage) == 'undefined'
3479
3849
  ||
3480
- typeof(requestStorage) != 'undefined'
3481
- && typeof(requestStorage.haltedRequest) == 'undefined'
3850
+ typeof(requestStorage) != 'undefined'
3851
+ && typeof(requestStorage.haltedRequest) == 'undefined'
3482
3852
  ) {
3483
3853
  var error = new ApiError('`requestStorage.haltedRequest` is required', 424);
3484
3854
  self.throwError(error);
@@ -3493,11 +3863,11 @@ function SuperController(options) {
3493
3863
  if (req.method.toLowerCase() == method) {
3494
3864
  data = merge(data, req[method])
3495
3865
  }
3496
-
3497
- delete req[method];
3866
+
3867
+ delete req[method];
3498
3868
  }
3499
-
3500
-
3869
+
3870
+
3501
3871
  var dataAsParams = {};
3502
3872
  if (data.count() > 0) {
3503
3873
  dataAsParams = JSON.clone(haltedRequest.data);
@@ -3509,25 +3879,50 @@ function SuperController(options) {
3509
3879
  requiredController = self.requireController(haltedRequest.routing.namespace, self._options );
3510
3880
  } catch (err) {
3511
3881
  self.throwError(err);
3512
- }
3882
+ }
3513
3883
  }
3514
3884
  req.routing = haltedRequest.routing;
3515
3885
  req.method = haltedRequest.method;
3516
3886
  req[haltedRequest.method] = data;
3517
-
3887
+
3518
3888
  local.haltedRequestUrlResumed = true;
3519
- if ( /GET/i.test(req.method) ) {
3889
+ if ( /GET/i.test(req.method) ) {
3520
3890
  if ( typeof(requestStorage.haltedRequest) != 'undefined' ) {
3521
3891
  delete requestStorage.haltedRequest;
3522
3892
  }
3523
3893
  delete requestStorage.haltedRequest;
3524
3894
  delete requestStorage.inheritedData;
3525
3895
  requestStorage.haltedRequestUrlResumed = url;
3526
-
3896
+
3897
+ if (
3898
+ typeof(req.routing.param.isPopinContext) != 'undefined'
3899
+ && /^true$/i.test(req.routing.param.isPopinContext)
3900
+ && self.isXMLRequest()
3901
+ ||
3902
+ self.isPopinContext()
3903
+ && self.isXMLRequest()
3904
+ ) {
3905
+ // return self.renderJSON({
3906
+ // isXhrRedirect: true,
3907
+ // popin: {
3908
+ // location: url
3909
+ // }
3910
+ // })
3911
+ self.redirect(url, true);
3912
+ return;
3913
+ }
3914
+ else if (self.isXMLRequest() ) {
3915
+ return self.renderJSON({
3916
+ isXhrRedirect: true,
3917
+ location: url
3918
+ })
3919
+ }
3920
+
3527
3921
  requiredController.redirect(url, true);
3922
+
3528
3923
  } else {
3529
3924
  local.onHaltedRequestResumed = function(err) {
3530
- if (!err) {
3925
+ if (!err) {
3531
3926
  delete requestStorage.haltedRequest;
3532
3927
  delete requestStorage.inheritedData;
3533
3928
  }
@@ -3535,7 +3930,7 @@ function SuperController(options) {
3535
3930
  if ( typeof(next) == 'function' ) {
3536
3931
  console.warn('About to override `next` param');
3537
3932
  }
3538
-
3933
+
3539
3934
  try {
3540
3935
  requiredController[req.routing.param.control](req, res, next);
3541
3936
  // consuming it
@@ -3544,12 +3939,12 @@ function SuperController(options) {
3544
3939
  console.error('[ BUNDLE ][ '+ local.options.conf.bundle +' ][ Controller ] Could not resume haltedRequest\n' + err.stack );
3545
3940
  self.throwError(err);
3546
3941
  }
3547
-
3548
-
3549
- }
3942
+
3943
+
3944
+ }
3550
3945
  }
3551
-
3552
-
3946
+
3947
+
3553
3948
  this.renderCustomError = function (req, res, next) {
3554
3949
 
3555
3950
  // preventing multiple call of self.renderWithoutLayout() when controller is rendering from another required controller
@@ -3559,16 +3954,19 @@ function SuperController(options) {
3559
3954
  local.options.isRenderingCustomError = true;
3560
3955
 
3561
3956
  //local.options.isWithoutLayout = true;
3562
-
3957
+
3563
3958
  var data = null;
3564
3959
  if ( typeof(req.routing.param.error) != 'undefined' ) {
3565
3960
  data = JSON.clone(req.routing.param.error) || {};
3566
3961
  delete req.routing.param.error
3567
3962
  }
3568
-
3963
+
3569
3964
  var session = getSession();
3570
3965
  if (session) {
3571
- data.session = JSON.clone(session)
3966
+ if (!data) {
3967
+ data = {}
3968
+ }
3969
+ data.session = ( typeof(session.user) != 'undefined' ) ? JSON.clone(session.user) : JSON.clone(session);
3572
3970
  }
3573
3971
  var displayToolbar = req.routing.param.displayToolbar || false;
3574
3972
  if (req.routing.param.displayToolbar) {
@@ -3603,13 +4001,27 @@ function SuperController(options) {
3603
4001
  //assets: {}
3604
4002
  };
3605
4003
  errOptions = merge(localOptions, local.options);
3606
-
3607
-
4004
+
4005
+
3608
4006
  }
3609
4007
  delete local.options.namespace;
3610
4008
  self.render(data, displayToolbar, errOptions);
3611
4009
  }
3612
-
4010
+
4011
+ var getResponseProtocol = function (response) {
4012
+ // var options = local.options;
4013
+ // var protocolVersion = ~~options.conf.server.protocol.match(/\/(.*)$/)[1].replace(/\.\d+/, '');
4014
+
4015
+ var protocol = 'http/'+ local.req.httpVersion; // inheriting request protocol version by default
4016
+ var bundleConf = options.conf;
4017
+ // switching protocol to h2 when possible
4018
+ if ( /http\/2/.test(bundleConf.server.protocol) && response.stream ) {
4019
+ protocol = bundleConf.server.protocol;
4020
+ }
4021
+
4022
+ return protocol;
4023
+ }
4024
+
3613
4025
 
3614
4026
  /**
3615
4027
  * Throw error
@@ -3621,9 +4033,14 @@ function SuperController(options) {
3621
4033
  * @returns {void}
3622
4034
  * */
3623
4035
  this.throwError = function(res, code, msg) {
4036
+
4037
+ var protocol = getResponseProtocol(res);
4038
+ var stream = ( /http\/2/.test(protocol) && res.stream ) ? res.stream : null;
4039
+ var header = ( /http\/2/.test(protocol) && res.stream ) ? {} : null;
4040
+
3624
4041
  self.isProcessingError = true;
3625
4042
  var errorObject = null; // to be returned
3626
-
4043
+
3627
4044
  // preventing multiple call of self.throwError() when controller is rendering from another required controller
3628
4045
  if (local.options.renderingStack.length > 1) {
3629
4046
  return false
@@ -3634,21 +4051,22 @@ function SuperController(options) {
3634
4051
  // err.fallback must be a valide route object or a url string
3635
4052
  var fallback = null;
3636
4053
  var standardErrorMessage = null;
3637
- if (
3638
- arguments[0] instanceof Error
4054
+ if (
4055
+ arguments[0] instanceof Error
3639
4056
  || arguments.length == 1 && typeof(res) == 'object'
3640
4057
  || arguments[arguments.length-1] instanceof Error
3641
- || typeof(arguments[arguments.length-1]) == 'string' && !(arguments[0] instanceof Error)
4058
+ || typeof(arguments[arguments.length-1]) == 'string' && !(arguments[0] instanceof Error)
3642
4059
  ) {
3643
-
3644
- code = ( res && typeof(res.status) != 'undefined' ) ? res.status : 500;
3645
-
4060
+
4061
+ msg = ( !/^\d+$/.test(code) && typeof(msg) == 'undefined' ) ? code : msg;
4062
+ code = ( res && typeof(res.status) != 'undefined' ) ? res.status : 500;
4063
+
3646
4064
  if ( typeof(statusCodes[code]) != 'undefined' ) {
3647
4065
  standardErrorMessage = statusCodes[code];
3648
4066
  } else {
3649
4067
  console.warn('[ ApiValidator ] statusCode `'+ code +'` not matching any definition in `'+_( getPath('gina').core + '/status.codes')+'`\nPlease contact the Gina dev team to add one if required');
3650
4068
  }
3651
-
4069
+
3652
4070
  errorObject = {
3653
4071
  status : code,
3654
4072
  error : res.error || res.message || standardErrorMessage
@@ -3663,17 +4081,33 @@ function SuperController(options) {
3663
4081
  } else if (res.message) {
3664
4082
  console.warn('[ Controller ] Ignoring message because of the format.\n'+res.message)
3665
4083
  }
3666
-
4084
+
4085
+ // ApiError merge
4086
+
4087
+
3667
4088
  } else if ( typeof(arguments[arguments.length-1]) == 'string' ) {
3668
4089
  // formated error
3669
- errorObject.message = arguments[arguments.length-1]
4090
+ errorObject.message = arguments[arguments.length-1] || msg
4091
+ // errorObject = merge(arguments[arguments.length-1], errorObject)
3670
4092
  } else if (
3671
- arguments[arguments.length-1] instanceof Error
3672
- || typeof(res) == 'object' && typeof(res.stack) != 'undefined'
4093
+ arguments[arguments.length-1] instanceof Error
4094
+ || typeof(res) == 'object' && typeof(res.stack) != 'undefined'
3673
4095
  ) {
3674
4096
  errorObject = merge(arguments[arguments.length-1], errorObject)
4097
+ } else if (
4098
+ !(arguments[arguments.length-1] instanceof Error)
4099
+ && typeof(res) == 'object'
4100
+ && typeof(res.error) != 'undefined'
4101
+ && typeof(res.fields) != 'undefined'
4102
+ ||
4103
+ !(arguments[arguments.length-1] instanceof Error)
4104
+ && typeof(res) == 'object'
4105
+ && typeof(res.error) != 'undefined'
4106
+ && typeof(res.flash) != 'undefined'
4107
+ ) { // ApiError merge
4108
+ errorObject = merge(arguments[arguments.length-1], errorObject)
3675
4109
  }
3676
-
4110
+
3677
4111
  if ( typeof(res.fallback) != 'undefined' ) {
3678
4112
  fallback = res.fallback
3679
4113
  }
@@ -3685,27 +4119,33 @@ function SuperController(options) {
3685
4119
  code = res || 500;
3686
4120
  res = local.res;
3687
4121
  }
3688
-
3689
- var responseHeaders = res.getHeaders() || local.res.getHeaders();
4122
+
4123
+ var responseHeaders = null;
4124
+ if ( typeof(res.getHeaders) == 'undefined' && typeof(res.stream) != 'undefined' ) {
4125
+ responseHeaders = res.stream.sentHeader;
4126
+ } else {
4127
+ responseHeaders = res.getHeaders() || local.res.getHeaders();
4128
+ }
4129
+ // var responseHeaders = res.getHeaders() || local.res.getHeaders();
3690
4130
  var req = local.req;
3691
4131
  var next = local.next;
3692
- if (!res.headersSent) {
4132
+ if (!headersSent()) {
3693
4133
  // DELETE request methods don't normaly use a view,
3694
4134
  // but if we are calling it from a view, we should render the error back to the view
3695
- if ( self.isXMLRequest() || !hasViews() && !/delete/i.test(req.method) || !local.options.isUsingTemplate && !hasViews() || hasViews() && !local.options.isUsingTemplate ) {
4135
+ if ( self.isXMLRequest() || !hasViews() && !/delete/i.test(req.method) || !local.options.isUsingTemplate && !hasViews() || hasViews() && !local.options.isUsingTemplate ) {
3696
4136
  // fallback interception
3697
- if ( fallback ) {
4137
+ if ( fallback ) {
3698
4138
  if ( typeof(fallback) == 'string' ){ // string url: user provided
3699
4139
  return self.redirect( fallback, true )
3700
4140
  } else {
3701
4141
  // else, using url from route object
3702
4142
  // Reminder
3703
4143
  // Here, we use route.toUrl() intead of
3704
- // route.url to support x-bundle com
4144
+ // route.url to support x-bundle com
3705
4145
  return self.redirect( fallback.toUrl() );
3706
4146
  }
3707
4147
  }
3708
-
4148
+
3709
4149
  // allowing this.throwError(err)
3710
4150
  if ( typeof(code) == 'object' && !msg && typeof(code.status) != 'undefined' && typeof(code.error) != 'undefined' ) {
3711
4151
  msg = code.error || code.message;
@@ -3717,7 +4157,7 @@ function SuperController(options) {
3717
4157
  console.warn('[ ApiValidator ] statusCode `'+ code +'` not matching any definition in `'+_( getPath('gina').core + '/status.codes')+'`\nPlease contact the Gina dev team to add one if required');
3718
4158
  }
3719
4159
 
3720
- // if ( !local.res.getHeaders()['content-type'] /**!req.headers['content-type'] */  ) {
4160
+ // if ( !local.res.getHeaders()['content-type'] /**!req.headers['content-type'] */ ) {
3721
4161
  // // Internet Explorer override
3722
4162
  // if ( typeof(req.headers['user-agent']) != 'undefined' && /msie/i.test(req.headers['user-agent']) ) {
3723
4163
  // res.writeHead(code, "content-type", "text/plain")
@@ -3725,7 +4165,7 @@ function SuperController(options) {
3725
4165
  // res.writeHead(code, { 'content-type': bundleConf.server.coreConfiguration.mime['json']} );
3726
4166
  // }
3727
4167
  // }
3728
-
4168
+
3729
4169
  // TODO - test with internet explorer then remove this if working
3730
4170
  if ( typeof(req.headers['user-agent']) != 'undefined' ) {
3731
4171
  if ( /msie/i.test(req.headers['user-agent']) ) {
@@ -3743,8 +4183,8 @@ function SuperController(options) {
3743
4183
  res.writeHead(code, "content-type", bundleConf.server.coreConfiguration.mime['json']+ '; charset='+ bundleConf.encoding);
3744
4184
  }
3745
4185
 
3746
-
3747
-
4186
+
4187
+
3748
4188
  if (!errorObject) {
3749
4189
  errorObject = {
3750
4190
  status: code,
@@ -3754,7 +4194,7 @@ function SuperController(options) {
3754
4194
  stack: msg.stack
3755
4195
  }
3756
4196
  }
3757
-
4197
+
3758
4198
  var errOutput = null, output = errorObject.toString();
3759
4199
  if ( output == '[object Object]' ) {
3760
4200
  errOutput = JSON.stringify(errorObject);
@@ -3762,21 +4202,23 @@ function SuperController(options) {
3762
4202
  errOutput = JSON.stringify(
3763
4203
  {
3764
4204
  status : errorObject.status,
3765
- error : output
4205
+ error : output,
4206
+ stack : errorObject.stack || null
3766
4207
  }
3767
4208
  );
3768
4209
  }
3769
-
3770
- console.error('[ BUNDLE ][ '+ bundleConf.bundle +' ][ Controller ] '+ req.method +' ['+res.statusCode +'] '+ req.url +'\n'+ errOutput);
4210
+
4211
+ // console.error('[ BUNDLE ][ '+ bundleConf.bundle +' ][ Controller ] '+ req.method +' ['+res.statusCode +'] '+ req.url +'\n'+ errorObject);
4212
+ console.error('[ BUNDLE ][ '+ bundleConf.bundle +' ][ Controller ] '+ req.method +' ['+res.statusCode +'] '+ req.url +'\n'+ errOutput);
3771
4213
  return res.end(errOutput);
3772
4214
  } else {
3773
-
3774
-
3775
- console.error(req.method +' ['+ errorObject.status +'] '+ req.url);
3776
-
3777
-
4215
+
4216
+
4217
+ console.error(req.method +' ['+ errorObject.status +'] '+ req.url + '\n'+ (errorObject.stack||errorObject.message));
4218
+
4219
+
3778
4220
  // intercept none HTML mime types
3779
- var url = unescape(local.req.url) /// avoid %20
4221
+ var url = decodeURI(local.req.url) /// avoid %20
3780
4222
  , ext = null
3781
4223
  , isHtmlContent = false
3782
4224
  , hasCustomErrorFile = false
@@ -3788,9 +4230,12 @@ function SuperController(options) {
3788
4230
  }
3789
4231
  if ( !ext || /^(html|htm)$/i.test(ext) ) {
3790
4232
  isHtmlContent = true;
4233
+ if (!ext) {
4234
+ ext = 'html'
4235
+ }
3791
4236
  }
3792
-
3793
- if (
4237
+
4238
+ if (
3794
4239
  isHtmlContent
3795
4240
  && typeof(bundleConf.content.templates._common.errorFiles) != 'undefined'
3796
4241
  && typeof(bundleConf.content.templates._common.errorFiles[code]) != 'undefined'
@@ -3810,11 +4255,11 @@ function SuperController(options) {
3810
4255
  //message : errorObject.message || msg || null,
3811
4256
  pathname : url
3812
4257
  };
3813
-
4258
+
3814
4259
  if ( errorObject ) {
3815
4260
  eData = merge(errorObject, eData);
3816
4261
  }
3817
-
4262
+
3818
4263
  if ( typeof(msg) == 'object' ) {
3819
4264
  if ( typeof(msg.stack) != 'undefined' ) {
3820
4265
  eData.stack = msg.stack
@@ -3823,8 +4268,8 @@ function SuperController(options) {
3823
4268
  eData.message = msg.message
3824
4269
  }
3825
4270
  }
3826
- if (
3827
- code
4271
+ if (
4272
+ code
3828
4273
  // See: framework/${version}/core/status.code
3829
4274
  && typeof(bundleConf.server.coreConfiguration.statusCodes[code]) != 'undefined'
3830
4275
  ) {
@@ -3834,33 +4279,33 @@ function SuperController(options) {
3834
4279
  // if ( typeof(local.req.routing) != 'undefined' ) {
3835
4280
  // eData.routing = local.req.routing;
3836
4281
  // }
3837
-
4282
+
3838
4283
  if (typeof(bundleConf.content.templates._common.errorFiles[code]) != 'undefined') {
3839
4284
  eFilename = bundleConf.content.templates._common.errorFiles[code];
3840
4285
  } else {
3841
4286
  eFilename = bundleConf.content.templates._common.errorFiles[eCode];
3842
4287
  }
3843
-
4288
+
3844
4289
  if (!local.options.isRenderingCustomError) {
3845
4290
  var eRule = 'custom-error-page@'+ bundle;
3846
4291
  var routeObj = bundleConf.content.routing[eRule];
3847
4292
  routeObj.rule = eRule;
3848
- //routeObj.url = unescape(local.req.url);/// avoid %20
4293
+ //routeObj.url = decodeURI(local.req.url);/// avoid %20
3849
4294
  routeObj.param.title = ( typeof(eData.title) != 'undefined' ) ? eData.title : 'Error ' + eData.status;
3850
4295
  routeObj.param.file = eFilename;
3851
4296
  routeObj.param.error = eData;
3852
4297
  routeObj.param.displayToolbar = self.isCacheless();
3853
4298
  routeObj.param.isLocalOptionResetNeeded = true;
3854
-
3855
-
4299
+
4300
+
3856
4301
  local.req.routing = routeObj;
3857
4302
  local.req.params.errorObject = errorObject;
3858
4303
  self.renderCustomError(local.req, res, local.next);
3859
4304
  return;
3860
4305
  }
3861
-
4306
+
3862
4307
  }
3863
-
4308
+
3864
4309
  // if (!errorObject) {
3865
4310
  // errorObject = {
3866
4311
  // status: code,
@@ -3871,7 +4316,7 @@ function SuperController(options) {
3871
4316
  // }
3872
4317
  // }
3873
4318
  var msgString = '<h1 class="status">Error '+ code +'.</h1>';
3874
-
4319
+
3875
4320
  console.error('[ BUNDLE ][ '+ local.options.conf.bundle +' ][ Controller ] `this.'+ req.routing.param.control +'(...)` ['+res.statusCode +'] '+ req.url);
3876
4321
  if ( typeof(msg) == 'object' ) {
3877
4322
 
@@ -3913,7 +4358,7 @@ function SuperController(options) {
3913
4358
  if (typeof(errorObject) != 'undefined' && errorObject && typeof(errorObject.stack) != 'undefined' ) {
3914
4359
  stack = errorObject.stack
3915
4360
  }
3916
-
4361
+
3917
4362
  if (title) {
3918
4363
  msgString += '<pre class="'+ eCode +' title">'+ title +'</pre>';
3919
4364
  }
@@ -3922,7 +4367,7 @@ function SuperController(options) {
3922
4367
  }
3923
4368
  if (stack) {
3924
4369
  msgString += '<pre class="'+ eCode +' stack">'+ stack +'</pre>';
3925
- }
4370
+ }
3926
4371
  }
3927
4372
  res.writeHead(code, { 'content-type': bundleConf.server.coreConfiguration.mime[ext]+'; charset='+ bundleConf.encoding } );
3928
4373
  // if ( isHtmlContent && hasCustomErrorFile ) {
@@ -3931,15 +4376,19 @@ function SuperController(options) {
3931
4376
  //if ( isHtmlContent && !hasCustomErrorFile ) {
3932
4377
  res.end(msgString);
3933
4378
  //}
3934
-
4379
+
3935
4380
  return;
3936
4381
  }
3937
4382
  } else {
3938
4383
  if (typeof(next) != 'undefined')
3939
4384
  return next();
3940
4385
  }
3941
- res.end();
3942
- return;
4386
+
4387
+ if ( /http\/2/.test(protocol) ) {
4388
+ return stream.end();
4389
+ }
4390
+
4391
+ return res.end();
3943
4392
  }
3944
4393
 
3945
4394
  // converting references to objects