gina 0.1.1-alpha.23 → 0.1.1-alpha.230

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