gina 0.1.1-alpha.18 → 0.1.1-alpha.181

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