@nocobase/plugin-idp-oauth 2.1.0-alpha.10

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 (451) hide show
  1. package/LICENSE.txt +107 -0
  2. package/README.md +14 -0
  3. package/build.config.ts +46 -0
  4. package/client.d.ts +2 -0
  5. package/client.js +1 -0
  6. package/dist/client/ErrorPage.d.ts +11 -0
  7. package/dist/client/InteractionPage.d.ts +11 -0
  8. package/dist/client/index.d.ts +9 -0
  9. package/dist/client/index.js +10 -0
  10. package/dist/client/locale.d.ts +10 -0
  11. package/dist/client/models/index.d.ts +11 -0
  12. package/dist/client/plugin.d.ts +13 -0
  13. package/dist/externalVersion.js +18 -0
  14. package/dist/index.d.ts +10 -0
  15. package/dist/index.js +48 -0
  16. package/dist/locale/en-US.json +1 -0
  17. package/dist/locale/zh-CN.json +1 -0
  18. package/dist/node_modules/eta/LICENSE +7 -0
  19. package/dist/node_modules/eta/README.md +185 -0
  20. package/dist/node_modules/eta/dist/core.d.ts +179 -0
  21. package/dist/node_modules/eta/dist/core.d.ts.map +1 -0
  22. package/dist/node_modules/eta/dist/core.js +42 -0
  23. package/dist/node_modules/eta/dist/core.js.map +1 -0
  24. package/dist/node_modules/eta/dist/index.cjs +542 -0
  25. package/dist/node_modules/eta/dist/index.cjs.map +1 -0
  26. package/dist/node_modules/eta/dist/index.d.cts +187 -0
  27. package/dist/node_modules/eta/dist/index.d.cts.map +1 -0
  28. package/dist/node_modules/eta/dist/index.d.mts +187 -0
  29. package/dist/node_modules/eta/dist/index.d.mts.map +1 -0
  30. package/dist/node_modules/eta/dist/index.mjs +512 -0
  31. package/dist/node_modules/eta/dist/index.mjs.map +1 -0
  32. package/dist/node_modules/eta/package.json +75 -0
  33. package/dist/node_modules/jose/LICENSE.md +21 -0
  34. package/dist/node_modules/jose/README.md +153 -0
  35. package/dist/node_modules/jose/dist/types/index.d.ts +55 -0
  36. package/dist/node_modules/jose/dist/types/jwe/compact/decrypt.d.ts +31 -0
  37. package/dist/node_modules/jose/dist/types/jwe/compact/encrypt.d.ts +65 -0
  38. package/dist/node_modules/jose/dist/types/jwe/flattened/decrypt.d.ts +31 -0
  39. package/dist/node_modules/jose/dist/types/jwe/flattened/encrypt.d.ts +83 -0
  40. package/dist/node_modules/jose/dist/types/jwe/general/decrypt.d.ts +38 -0
  41. package/dist/node_modules/jose/dist/types/jwe/general/encrypt.d.ts +74 -0
  42. package/dist/node_modules/jose/dist/types/jwk/embedded.d.ts +17 -0
  43. package/dist/node_modules/jose/dist/types/jwk/thumbprint.d.ts +32 -0
  44. package/dist/node_modules/jose/dist/types/jwks/local.d.ts +29 -0
  45. package/dist/node_modules/jose/dist/types/jwks/remote.d.ts +237 -0
  46. package/dist/node_modules/jose/dist/types/jws/compact/sign.d.ts +36 -0
  47. package/dist/node_modules/jose/dist/types/jws/compact/verify.d.ts +33 -0
  48. package/dist/node_modules/jose/dist/types/jws/flattened/sign.d.ts +42 -0
  49. package/dist/node_modules/jose/dist/types/jws/flattened/verify.d.ts +33 -0
  50. package/dist/node_modules/jose/dist/types/jws/general/sign.d.ts +53 -0
  51. package/dist/node_modules/jose/dist/types/jws/general/verify.d.ts +41 -0
  52. package/dist/node_modules/jose/dist/types/jwt/decrypt.d.ts +35 -0
  53. package/dist/node_modules/jose/dist/types/jwt/encrypt.d.ts +91 -0
  54. package/dist/node_modules/jose/dist/types/jwt/sign.d.ts +43 -0
  55. package/dist/node_modules/jose/dist/types/jwt/unsecured.d.ts +43 -0
  56. package/dist/node_modules/jose/dist/types/jwt/verify.d.ts +37 -0
  57. package/dist/node_modules/jose/dist/types/key/export.d.ts +33 -0
  58. package/dist/node_modules/jose/dist/types/key/generate_key_pair.d.ts +47 -0
  59. package/dist/node_modules/jose/dist/types/key/generate_secret.d.ts +35 -0
  60. package/dist/node_modules/jose/dist/types/key/import.d.ts +83 -0
  61. package/dist/node_modules/jose/dist/types/types.d.ts +852 -0
  62. package/dist/node_modules/jose/dist/types/util/base64url.d.ts +9 -0
  63. package/dist/node_modules/jose/dist/types/util/decode_jwt.d.ts +18 -0
  64. package/dist/node_modules/jose/dist/types/util/decode_protected_header.d.ts +17 -0
  65. package/dist/node_modules/jose/dist/types/util/errors.d.ts +213 -0
  66. package/dist/node_modules/jose/dist/webapi/index.js +32 -0
  67. package/dist/node_modules/jose/dist/webapi/jwe/compact/decrypt.js +27 -0
  68. package/dist/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +27 -0
  69. package/dist/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +155 -0
  70. package/dist/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +165 -0
  71. package/dist/node_modules/jose/dist/webapi/jwe/general/decrypt.js +31 -0
  72. package/dist/node_modules/jose/dist/webapi/jwe/general/encrypt.js +182 -0
  73. package/dist/node_modules/jose/dist/webapi/jwk/embedded.js +17 -0
  74. package/dist/node_modules/jose/dist/webapi/jwk/thumbprint.js +68 -0
  75. package/dist/node_modules/jose/dist/webapi/jwks/local.js +119 -0
  76. package/dist/node_modules/jose/dist/webapi/jwks/remote.js +179 -0
  77. package/dist/node_modules/jose/dist/webapi/jws/compact/sign.js +18 -0
  78. package/dist/node_modules/jose/dist/webapi/jws/compact/verify.js +21 -0
  79. package/dist/node_modules/jose/dist/webapi/jws/flattened/sign.js +89 -0
  80. package/dist/node_modules/jose/dist/webapi/jws/flattened/verify.js +110 -0
  81. package/dist/node_modules/jose/dist/webapi/jws/general/sign.js +70 -0
  82. package/dist/node_modules/jose/dist/webapi/jws/general/verify.js +24 -0
  83. package/dist/node_modules/jose/dist/webapi/jwt/decrypt.js +23 -0
  84. package/dist/node_modules/jose/dist/webapi/jwt/encrypt.js +101 -0
  85. package/dist/node_modules/jose/dist/webapi/jwt/sign.js +52 -0
  86. package/dist/node_modules/jose/dist/webapi/jwt/unsecured.js +63 -0
  87. package/dist/node_modules/jose/dist/webapi/jwt/verify.js +15 -0
  88. package/dist/node_modules/jose/dist/webapi/key/export.js +11 -0
  89. package/dist/node_modules/jose/dist/webapi/key/generate_key_pair.js +97 -0
  90. package/dist/node_modules/jose/dist/webapi/key/generate_secret.js +40 -0
  91. package/dist/node_modules/jose/dist/webapi/key/import.js +57 -0
  92. package/dist/node_modules/jose/dist/webapi/lib/aesgcmkw.js +15 -0
  93. package/dist/node_modules/jose/dist/webapi/lib/aeskw.js +25 -0
  94. package/dist/node_modules/jose/dist/webapi/lib/asn1.js +243 -0
  95. package/dist/node_modules/jose/dist/webapi/lib/base64.js +22 -0
  96. package/dist/node_modules/jose/dist/webapi/lib/buffer_utils.js +43 -0
  97. package/dist/node_modules/jose/dist/webapi/lib/check_key_type.js +122 -0
  98. package/dist/node_modules/jose/dist/webapi/lib/content_encryption.js +217 -0
  99. package/dist/node_modules/jose/dist/webapi/lib/crypto_key.js +136 -0
  100. package/dist/node_modules/jose/dist/webapi/lib/deflate.js +44 -0
  101. package/dist/node_modules/jose/dist/webapi/lib/ecdhes.js +52 -0
  102. package/dist/node_modules/jose/dist/webapi/lib/helpers.js +19 -0
  103. package/dist/node_modules/jose/dist/webapi/lib/invalid_key_input.js +27 -0
  104. package/dist/node_modules/jose/dist/webapi/lib/is_key_like.js +17 -0
  105. package/dist/node_modules/jose/dist/webapi/lib/jwk_to_key.js +107 -0
  106. package/dist/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +238 -0
  107. package/dist/node_modules/jose/dist/webapi/lib/key_management.js +186 -0
  108. package/dist/node_modules/jose/dist/webapi/lib/key_to_jwk.js +31 -0
  109. package/dist/node_modules/jose/dist/webapi/lib/normalize_key.js +166 -0
  110. package/dist/node_modules/jose/dist/webapi/lib/pbes2kw.js +39 -0
  111. package/dist/node_modules/jose/dist/webapi/lib/rsaes.js +24 -0
  112. package/dist/node_modules/jose/dist/webapi/lib/signing.js +68 -0
  113. package/dist/node_modules/jose/dist/webapi/lib/type_checks.js +40 -0
  114. package/dist/node_modules/jose/dist/webapi/lib/validate_algorithms.js +10 -0
  115. package/dist/node_modules/jose/dist/webapi/lib/validate_crit.js +33 -0
  116. package/dist/node_modules/jose/dist/webapi/util/base64url.js +30 -0
  117. package/dist/node_modules/jose/dist/webapi/util/decode_jwt.js +32 -0
  118. package/dist/node_modules/jose/dist/webapi/util/decode_protected_header.js +34 -0
  119. package/dist/node_modules/jose/dist/webapi/util/errors.js +99 -0
  120. package/dist/node_modules/jose/package.json +200 -0
  121. package/dist/node_modules/light-my-request/.gitattributes +2 -0
  122. package/dist/node_modules/light-my-request/.github/dependabot.yml +13 -0
  123. package/dist/node_modules/light-my-request/.github/stale.yml +21 -0
  124. package/dist/node_modules/light-my-request/.github/workflows/benchmark.yml +30 -0
  125. package/dist/node_modules/light-my-request/.github/workflows/ci.yml +23 -0
  126. package/dist/node_modules/light-my-request/LICENSE +32 -0
  127. package/dist/node_modules/light-my-request/benchmark/benchmark.js +164 -0
  128. package/dist/node_modules/light-my-request/build/build-validation.js +100 -0
  129. package/dist/node_modules/light-my-request/eslint.config.js +9 -0
  130. package/dist/node_modules/light-my-request/index.js +2 -0
  131. package/dist/node_modules/light-my-request/lib/config-validator.js +919 -0
  132. package/dist/node_modules/light-my-request/lib/form-data.js +79 -0
  133. package/dist/node_modules/light-my-request/lib/parse-url.js +47 -0
  134. package/dist/node_modules/light-my-request/lib/request.js +290 -0
  135. package/dist/node_modules/light-my-request/lib/response.js +240 -0
  136. package/dist/node_modules/light-my-request/node_modules/process-warning/.gitattributes +2 -0
  137. package/dist/node_modules/light-my-request/node_modules/process-warning/.github/dependabot.yml +13 -0
  138. package/dist/node_modules/light-my-request/node_modules/process-warning/.github/workflows/ci.yml +24 -0
  139. package/dist/node_modules/light-my-request/node_modules/process-warning/.taprc +2 -0
  140. package/dist/node_modules/light-my-request/node_modules/process-warning/benchmarks/warn.js +25 -0
  141. package/dist/node_modules/light-my-request/node_modules/process-warning/eslint.config.js +6 -0
  142. package/dist/node_modules/light-my-request/node_modules/process-warning/examples/example.js +11 -0
  143. package/dist/node_modules/light-my-request/node_modules/process-warning/index.js +124 -0
  144. package/dist/node_modules/light-my-request/node_modules/process-warning/package.json +73 -0
  145. package/dist/node_modules/light-my-request/node_modules/process-warning/test/emit-interpolated-string.test.js +29 -0
  146. package/dist/node_modules/light-my-request/node_modules/process-warning/test/emit-once-only.test.js +28 -0
  147. package/dist/node_modules/light-my-request/node_modules/process-warning/test/emit-reset.test.js +36 -0
  148. package/dist/node_modules/light-my-request/node_modules/process-warning/test/emit-set.test.js +30 -0
  149. package/dist/node_modules/light-my-request/node_modules/process-warning/test/emit-unlimited.test.js +37 -0
  150. package/dist/node_modules/light-my-request/node_modules/process-warning/test/index.test.js +99 -0
  151. package/dist/node_modules/light-my-request/node_modules/process-warning/test/issue-88.test.js +33 -0
  152. package/dist/node_modules/light-my-request/node_modules/process-warning/test/jest.test.js +22 -0
  153. package/dist/node_modules/light-my-request/node_modules/process-warning/test/no-warnings.test.js +80 -0
  154. package/dist/node_modules/light-my-request/node_modules/process-warning/types/index.d.ts +37 -0
  155. package/dist/node_modules/light-my-request/node_modules/process-warning/types/index.test-d.ts +36 -0
  156. package/dist/node_modules/light-my-request/package.json +1 -0
  157. package/dist/node_modules/light-my-request/test/async-await.test.js +55 -0
  158. package/dist/node_modules/light-my-request/test/index.test.js +2316 -0
  159. package/dist/node_modules/light-my-request/test/request.test.js +16 -0
  160. package/dist/node_modules/light-my-request/test/response.test.js +19 -0
  161. package/dist/node_modules/light-my-request/test/stream.test.js +359 -0
  162. package/dist/node_modules/light-my-request/types/index.d.ts +128 -0
  163. package/dist/node_modules/light-my-request/types/index.test-d.ts +149 -0
  164. package/dist/node_modules/oidc-provider/LICENSE.md +21 -0
  165. package/dist/node_modules/oidc-provider/README.md +174 -0
  166. package/dist/node_modules/oidc-provider/lib/actions/authorization/assign_claims.js +28 -0
  167. package/dist/node_modules/oidc-provider/lib/actions/authorization/assign_defaults.js +17 -0
  168. package/dist/node_modules/oidc-provider/lib/actions/authorization/authenticated_client_id.js +6 -0
  169. package/dist/node_modules/oidc-provider/lib/actions/authorization/backchannel_request_remap_errors.js +17 -0
  170. package/dist/node_modules/oidc-provider/lib/actions/authorization/backchannel_request_response.js +41 -0
  171. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_ciba_context.js +12 -0
  172. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_claims.js +68 -0
  173. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_client.js +21 -0
  174. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_client_grant_type.js +21 -0
  175. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_dpop_jkt.js +35 -0
  176. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_extra_params.js +18 -0
  177. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_id_token_hint.js +23 -0
  178. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_max_age.js +25 -0
  179. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_openid_scope.js +47 -0
  180. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_pkce.js +41 -0
  181. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_prompt.js +25 -0
  182. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_redirect_uri.js +41 -0
  183. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_requested_expiry.js +16 -0
  184. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_response_mode.js +54 -0
  185. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_response_type.js +26 -0
  186. package/dist/node_modules/oidc-provider/lib/actions/authorization/check_scope.js +53 -0
  187. package/dist/node_modules/oidc-provider/lib/actions/authorization/ciba_load_account.js +58 -0
  188. package/dist/node_modules/oidc-provider/lib/actions/authorization/ciba_required.js +13 -0
  189. package/dist/node_modules/oidc-provider/lib/actions/authorization/device_authorization_response.js +31 -0
  190. package/dist/node_modules/oidc-provider/lib/actions/authorization/device_user_flow.js +31 -0
  191. package/dist/node_modules/oidc-provider/lib/actions/authorization/device_user_flow_errors.js +37 -0
  192. package/dist/node_modules/oidc-provider/lib/actions/authorization/device_user_flow_response.js +55 -0
  193. package/dist/node_modules/oidc-provider/lib/actions/authorization/index.js +200 -0
  194. package/dist/node_modules/oidc-provider/lib/actions/authorization/interaction_emit.js +9 -0
  195. package/dist/node_modules/oidc-provider/lib/actions/authorization/interactions.js +149 -0
  196. package/dist/node_modules/oidc-provider/lib/actions/authorization/load_account.js +15 -0
  197. package/dist/node_modules/oidc-provider/lib/actions/authorization/load_grant.js +29 -0
  198. package/dist/node_modules/oidc-provider/lib/actions/authorization/load_pushed_authorization_request.js +36 -0
  199. package/dist/node_modules/oidc-provider/lib/actions/authorization/oauth_required.js +11 -0
  200. package/dist/node_modules/oidc-provider/lib/actions/authorization/oidc_required.js +27 -0
  201. package/dist/node_modules/oidc-provider/lib/actions/authorization/one_redirect_uri_clients.js +20 -0
  202. package/dist/node_modules/oidc-provider/lib/actions/authorization/process_request_object.js +214 -0
  203. package/dist/node_modules/oidc-provider/lib/actions/authorization/pushed_authorization_request_remap_errors.js +17 -0
  204. package/dist/node_modules/oidc-provider/lib/actions/authorization/pushed_authorization_request_response.js +65 -0
  205. package/dist/node_modules/oidc-provider/lib/actions/authorization/reject_registration.js +12 -0
  206. package/dist/node_modules/oidc-provider/lib/actions/authorization/reject_request_and_uri.js +12 -0
  207. package/dist/node_modules/oidc-provider/lib/actions/authorization/reject_unsupported.js +33 -0
  208. package/dist/node_modules/oidc-provider/lib/actions/authorization/respond.js +46 -0
  209. package/dist/node_modules/oidc-provider/lib/actions/authorization/resume.js +111 -0
  210. package/dist/node_modules/oidc-provider/lib/actions/authorization/strip_outside_jar_params.js +19 -0
  211. package/dist/node_modules/oidc-provider/lib/actions/authorization/unsupported_rar.js +9 -0
  212. package/dist/node_modules/oidc-provider/lib/actions/challenge.js +22 -0
  213. package/dist/node_modules/oidc-provider/lib/actions/code_verification.js +122 -0
  214. package/dist/node_modules/oidc-provider/lib/actions/discovery.js +151 -0
  215. package/dist/node_modules/oidc-provider/lib/actions/end_session.js +222 -0
  216. package/dist/node_modules/oidc-provider/lib/actions/grants/authorization_code.js +144 -0
  217. package/dist/node_modules/oidc-provider/lib/actions/grants/ciba.js +127 -0
  218. package/dist/node_modules/oidc-provider/lib/actions/grants/client_credentials.js +79 -0
  219. package/dist/node_modules/oidc-provider/lib/actions/grants/device_code.js +125 -0
  220. package/dist/node_modules/oidc-provider/lib/actions/grants/index.js +7 -0
  221. package/dist/node_modules/oidc-provider/lib/actions/grants/refresh_token.js +229 -0
  222. package/dist/node_modules/oidc-provider/lib/actions/index.js +25 -0
  223. package/dist/node_modules/oidc-provider/lib/actions/interaction.js +150 -0
  224. package/dist/node_modules/oidc-provider/lib/actions/introspection.js +164 -0
  225. package/dist/node_modules/oidc-provider/lib/actions/jwks.js +7 -0
  226. package/dist/node_modules/oidc-provider/lib/actions/registration.js +274 -0
  227. package/dist/node_modules/oidc-provider/lib/actions/revocation.js +81 -0
  228. package/dist/node_modules/oidc-provider/lib/actions/token.js +74 -0
  229. package/dist/node_modules/oidc-provider/lib/actions/userinfo.js +183 -0
  230. package/dist/node_modules/oidc-provider/lib/adapters/memory_adapter.js +95 -0
  231. package/dist/node_modules/oidc-provider/lib/consts/client_attributes.js +211 -0
  232. package/dist/node_modules/oidc-provider/lib/consts/dev_keystore.js +18 -0
  233. package/dist/node_modules/oidc-provider/lib/consts/index.js +13 -0
  234. package/dist/node_modules/oidc-provider/lib/consts/jwa.js +47 -0
  235. package/dist/node_modules/oidc-provider/lib/consts/non_rejectable_claims.js +1 -0
  236. package/dist/node_modules/oidc-provider/lib/consts/param_list.js +23 -0
  237. package/dist/node_modules/oidc-provider/lib/helpers/_/camel_case.js +1 -0
  238. package/dist/node_modules/oidc-provider/lib/helpers/_/defaults.js +28 -0
  239. package/dist/node_modules/oidc-provider/lib/helpers/_/difference.js +1 -0
  240. package/dist/node_modules/oidc-provider/lib/helpers/_/is_plain_object.js +1 -0
  241. package/dist/node_modules/oidc-provider/lib/helpers/_/map_keys.js +9 -0
  242. package/dist/node_modules/oidc-provider/lib/helpers/_/merge.js +25 -0
  243. package/dist/node_modules/oidc-provider/lib/helpers/_/omit_by.js +11 -0
  244. package/dist/node_modules/oidc-provider/lib/helpers/_/pick.js +10 -0
  245. package/dist/node_modules/oidc-provider/lib/helpers/_/pick_by.js +10 -0
  246. package/dist/node_modules/oidc-provider/lib/helpers/_/remove.js +9 -0
  247. package/dist/node_modules/oidc-provider/lib/helpers/_/set.js +18 -0
  248. package/dist/node_modules/oidc-provider/lib/helpers/_/snake_case.js +1 -0
  249. package/dist/node_modules/oidc-provider/lib/helpers/_/upper_first.js +1 -0
  250. package/dist/node_modules/oidc-provider/lib/helpers/account_claims.js +6 -0
  251. package/dist/node_modules/oidc-provider/lib/helpers/add_client.js +14 -0
  252. package/dist/node_modules/oidc-provider/lib/helpers/als.js +3 -0
  253. package/dist/node_modules/oidc-provider/lib/helpers/append_www_authenticate.js +9 -0
  254. package/dist/node_modules/oidc-provider/lib/helpers/attention.js +23 -0
  255. package/dist/node_modules/oidc-provider/lib/helpers/base64url.js +11 -0
  256. package/dist/node_modules/oidc-provider/lib/helpers/certificate_thumbprint.js +15 -0
  257. package/dist/node_modules/oidc-provider/lib/helpers/challenge.js +111 -0
  258. package/dist/node_modules/oidc-provider/lib/helpers/check_attest_binding.js +10 -0
  259. package/dist/node_modules/oidc-provider/lib/helpers/claims.js +79 -0
  260. package/dist/node_modules/oidc-provider/lib/helpers/client_id_metadata_document.js +198 -0
  261. package/dist/node_modules/oidc-provider/lib/helpers/client_schema.js +700 -0
  262. package/dist/node_modules/oidc-provider/lib/helpers/combined_scope.js +17 -0
  263. package/dist/node_modules/oidc-provider/lib/helpers/configuration.js +544 -0
  264. package/dist/node_modules/oidc-provider/lib/helpers/constant_equals.js +20 -0
  265. package/dist/node_modules/oidc-provider/lib/helpers/defaults.js +3510 -0
  266. package/dist/node_modules/oidc-provider/lib/helpers/epoch_time.js +1 -0
  267. package/dist/node_modules/oidc-provider/lib/helpers/err_out.js +17 -0
  268. package/dist/node_modules/oidc-provider/lib/helpers/errors.js +161 -0
  269. package/dist/node_modules/oidc-provider/lib/helpers/features.js +51 -0
  270. package/dist/node_modules/oidc-provider/lib/helpers/fetch_body_check.js +25 -0
  271. package/dist/node_modules/oidc-provider/lib/helpers/fetch_request.js +221 -0
  272. package/dist/node_modules/oidc-provider/lib/helpers/filter_claims.js +16 -0
  273. package/dist/node_modules/oidc-provider/lib/helpers/formatters.js +24 -0
  274. package/dist/node_modules/oidc-provider/lib/helpers/grant_common.js +214 -0
  275. package/dist/node_modules/oidc-provider/lib/helpers/html_safe.js +19 -0
  276. package/dist/node_modules/oidc-provider/lib/helpers/initialize_adapter.js +24 -0
  277. package/dist/node_modules/oidc-provider/lib/helpers/initialize_app.js +243 -0
  278. package/dist/node_modules/oidc-provider/lib/helpers/initialize_clients.js +24 -0
  279. package/dist/node_modules/oidc-provider/lib/helpers/initialize_keystore.js +310 -0
  280. package/dist/node_modules/oidc-provider/lib/helpers/interaction_policy/check.js +21 -0
  281. package/dist/node_modules/oidc-provider/lib/helpers/interaction_policy/index.js +43 -0
  282. package/dist/node_modules/oidc-provider/lib/helpers/interaction_policy/prompt.js +95 -0
  283. package/dist/node_modules/oidc-provider/lib/helpers/interaction_policy/prompts/consent.js +105 -0
  284. package/dist/node_modules/oidc-provider/lib/helpers/interaction_policy/prompts/login.js +162 -0
  285. package/dist/node_modules/oidc-provider/lib/helpers/jwt.js +211 -0
  286. package/dist/node_modules/oidc-provider/lib/helpers/keystore.js +301 -0
  287. package/dist/node_modules/oidc-provider/lib/helpers/nanoid.js +5 -0
  288. package/dist/node_modules/oidc-provider/lib/helpers/oidc_context.js +284 -0
  289. package/dist/node_modules/oidc-provider/lib/helpers/params.js +27 -0
  290. package/dist/node_modules/oidc-provider/lib/helpers/pkce.js +30 -0
  291. package/dist/node_modules/oidc-provider/lib/helpers/pkce_format.js +17 -0
  292. package/dist/node_modules/oidc-provider/lib/helpers/process_response_types.js +202 -0
  293. package/dist/node_modules/oidc-provider/lib/helpers/re_render_errors.js +39 -0
  294. package/dist/node_modules/oidc-provider/lib/helpers/redirect_uri.js +16 -0
  295. package/dist/node_modules/oidc-provider/lib/helpers/resolve_resource.js +33 -0
  296. package/dist/node_modules/oidc-provider/lib/helpers/resolve_response_mode.js +7 -0
  297. package/dist/node_modules/oidc-provider/lib/helpers/resource_server.js +20 -0
  298. package/dist/node_modules/oidc-provider/lib/helpers/revoke.js +27 -0
  299. package/dist/node_modules/oidc-provider/lib/helpers/script_src_sha.js +21 -0
  300. package/dist/node_modules/oidc-provider/lib/helpers/sector_identifier.js +19 -0
  301. package/dist/node_modules/oidc-provider/lib/helpers/sector_validate.js +55 -0
  302. package/dist/node_modules/oidc-provider/lib/helpers/set_rt_bindings.js +21 -0
  303. package/dist/node_modules/oidc-provider/lib/helpers/token_find.js +51 -0
  304. package/dist/node_modules/oidc-provider/lib/helpers/type_validators.js +8 -0
  305. package/dist/node_modules/oidc-provider/lib/helpers/user_code_form.js +19 -0
  306. package/dist/node_modules/oidc-provider/lib/helpers/user_codes.js +38 -0
  307. package/dist/node_modules/oidc-provider/lib/helpers/valid_url.js +8 -0
  308. package/dist/node_modules/oidc-provider/lib/helpers/validate_dpop.js +129 -0
  309. package/dist/node_modules/oidc-provider/lib/helpers/validate_presence.js +17 -0
  310. package/dist/node_modules/oidc-provider/lib/helpers/weak_cache.js +11 -0
  311. package/dist/node_modules/oidc-provider/lib/index.js +21 -0
  312. package/dist/node_modules/oidc-provider/lib/models/access_token.js +31 -0
  313. package/dist/node_modules/oidc-provider/lib/models/authorization_code.js +27 -0
  314. package/dist/node_modules/oidc-provider/lib/models/backchannel_authentication_request.js +26 -0
  315. package/dist/node_modules/oidc-provider/lib/models/base_model.js +141 -0
  316. package/dist/node_modules/oidc-provider/lib/models/base_token.js +86 -0
  317. package/dist/node_modules/oidc-provider/lib/models/client.js +593 -0
  318. package/dist/node_modules/oidc-provider/lib/models/client_credentials.js +19 -0
  319. package/dist/node_modules/oidc-provider/lib/models/device_code.js +44 -0
  320. package/dist/node_modules/oidc-provider/lib/models/formats/dynamic.js +21 -0
  321. package/dist/node_modules/oidc-provider/lib/models/formats/index.js +14 -0
  322. package/dist/node_modules/oidc-provider/lib/models/formats/jwt.js +198 -0
  323. package/dist/node_modules/oidc-provider/lib/models/formats/opaque.js +58 -0
  324. package/dist/node_modules/oidc-provider/lib/models/grant.js +243 -0
  325. package/dist/node_modules/oidc-provider/lib/models/id_token.js +271 -0
  326. package/dist/node_modules/oidc-provider/lib/models/index.js +37 -0
  327. package/dist/node_modules/oidc-provider/lib/models/initial_access_token.js +12 -0
  328. package/dist/node_modules/oidc-provider/lib/models/interaction.js +73 -0
  329. package/dist/node_modules/oidc-provider/lib/models/mixins/apply.js +4 -0
  330. package/dist/node_modules/oidc-provider/lib/models/mixins/consumable.js +17 -0
  331. package/dist/node_modules/oidc-provider/lib/models/mixins/has_format.js +46 -0
  332. package/dist/node_modules/oidc-provider/lib/models/mixins/has_grant_id.js +12 -0
  333. package/dist/node_modules/oidc-provider/lib/models/mixins/has_grant_type.js +8 -0
  334. package/dist/node_modules/oidc-provider/lib/models/mixins/has_policies.js +38 -0
  335. package/dist/node_modules/oidc-provider/lib/models/mixins/is_attestation_constrained.js +15 -0
  336. package/dist/node_modules/oidc-provider/lib/models/mixins/is_sender_constrained.js +50 -0
  337. package/dist/node_modules/oidc-provider/lib/models/mixins/is_session_bound.js +38 -0
  338. package/dist/node_modules/oidc-provider/lib/models/mixins/set_audience.js +21 -0
  339. package/dist/node_modules/oidc-provider/lib/models/mixins/stores_auth.js +16 -0
  340. package/dist/node_modules/oidc-provider/lib/models/mixins/stores_pkce.js +9 -0
  341. package/dist/node_modules/oidc-provider/lib/models/pushed_authorization_request.js +21 -0
  342. package/dist/node_modules/oidc-provider/lib/models/refresh_token.js +47 -0
  343. package/dist/node_modules/oidc-provider/lib/models/registration_access_token.js +8 -0
  344. package/dist/node_modules/oidc-provider/lib/models/replay_detection.js +31 -0
  345. package/dist/node_modules/oidc-provider/lib/models/session.js +192 -0
  346. package/dist/node_modules/oidc-provider/lib/provider.js +453 -0
  347. package/dist/node_modules/oidc-provider/lib/response_modes/form_post.js +36 -0
  348. package/dist/node_modules/oidc-provider/lib/response_modes/fragment.js +7 -0
  349. package/dist/node_modules/oidc-provider/lib/response_modes/index.js +15 -0
  350. package/dist/node_modules/oidc-provider/lib/response_modes/jwt.js +43 -0
  351. package/dist/node_modules/oidc-provider/lib/response_modes/query.js +7 -0
  352. package/dist/node_modules/oidc-provider/lib/response_modes/web_message.js +55 -0
  353. package/dist/node_modules/oidc-provider/lib/shared/assemble_params.js +7 -0
  354. package/dist/node_modules/oidc-provider/lib/shared/attest_client_auth.js +111 -0
  355. package/dist/node_modules/oidc-provider/lib/shared/authorization_error_handler.js +104 -0
  356. package/dist/node_modules/oidc-provider/lib/shared/check_rar.js +75 -0
  357. package/dist/node_modules/oidc-provider/lib/shared/check_resource.js +77 -0
  358. package/dist/node_modules/oidc-provider/lib/shared/client_auth.js +263 -0
  359. package/dist/node_modules/oidc-provider/lib/shared/conditional_body.js +9 -0
  360. package/dist/node_modules/oidc-provider/lib/shared/cors.js +49 -0
  361. package/dist/node_modules/oidc-provider/lib/shared/error_handler.js +59 -0
  362. package/dist/node_modules/oidc-provider/lib/shared/jwt_client_auth.js +79 -0
  363. package/dist/node_modules/oidc-provider/lib/shared/no_cache.js +4 -0
  364. package/dist/node_modules/oidc-provider/lib/shared/reject_dupes.js +45 -0
  365. package/dist/node_modules/oidc-provider/lib/shared/reject_structured_tokens.js +18 -0
  366. package/dist/node_modules/oidc-provider/lib/shared/selective_body.js +60 -0
  367. package/dist/node_modules/oidc-provider/lib/shared/session.js +68 -0
  368. package/dist/node_modules/oidc-provider/lib/shared/set_www_authenticate_header.js +52 -0
  369. package/dist/node_modules/oidc-provider/lib/views/index.js +22 -0
  370. package/dist/node_modules/oidc-provider/lib/views/interaction.js +171 -0
  371. package/dist/node_modules/oidc-provider/lib/views/layout.js +237 -0
  372. package/dist/node_modules/oidc-provider/lib/views/login.js +43 -0
  373. package/dist/node_modules/oidc-provider/node_modules/@koa/router/LICENSE +21 -0
  374. package/dist/node_modules/oidc-provider/node_modules/@koa/router/README.md +1370 -0
  375. package/dist/node_modules/oidc-provider/node_modules/@koa/router/dist/index.d.mts +1003 -0
  376. package/dist/node_modules/oidc-provider/node_modules/@koa/router/dist/index.d.ts +1003 -0
  377. package/dist/node_modules/oidc-provider/node_modules/@koa/router/dist/index.js +1616 -0
  378. package/dist/node_modules/oidc-provider/node_modules/@koa/router/dist/index.mjs +1573 -0
  379. package/dist/node_modules/oidc-provider/node_modules/@koa/router/package.json +122 -0
  380. package/dist/node_modules/oidc-provider/node_modules/debug/LICENSE +20 -0
  381. package/dist/node_modules/oidc-provider/node_modules/debug/README.md +481 -0
  382. package/dist/node_modules/oidc-provider/node_modules/debug/package.json +64 -0
  383. package/dist/node_modules/oidc-provider/node_modules/debug/src/browser.js +272 -0
  384. package/dist/node_modules/oidc-provider/node_modules/debug/src/common.js +292 -0
  385. package/dist/node_modules/oidc-provider/node_modules/debug/src/index.js +10 -0
  386. package/dist/node_modules/oidc-provider/node_modules/debug/src/node.js +263 -0
  387. package/dist/node_modules/oidc-provider/node_modules/http-errors/HISTORY.md +186 -0
  388. package/dist/node_modules/oidc-provider/node_modules/http-errors/LICENSE +23 -0
  389. package/dist/node_modules/oidc-provider/node_modules/http-errors/README.md +169 -0
  390. package/dist/node_modules/oidc-provider/node_modules/http-errors/index.js +290 -0
  391. package/dist/node_modules/oidc-provider/node_modules/http-errors/package.json +54 -0
  392. package/dist/node_modules/oidc-provider/node_modules/jsesc/LICENSE-MIT.txt +20 -0
  393. package/dist/node_modules/oidc-provider/node_modules/jsesc/README.md +422 -0
  394. package/dist/node_modules/oidc-provider/node_modules/jsesc/bin/jsesc +148 -0
  395. package/dist/node_modules/oidc-provider/node_modules/jsesc/jsesc.js +337 -0
  396. package/dist/node_modules/oidc-provider/node_modules/jsesc/man/jsesc.1 +94 -0
  397. package/dist/node_modules/oidc-provider/node_modules/jsesc/package.json +56 -0
  398. package/dist/node_modules/oidc-provider/node_modules/nanoid/LICENSE +20 -0
  399. package/dist/node_modules/oidc-provider/node_modules/nanoid/README.md +38 -0
  400. package/dist/node_modules/oidc-provider/node_modules/nanoid/bin/nanoid.js +55 -0
  401. package/dist/node_modules/oidc-provider/node_modules/nanoid/index.browser.js +29 -0
  402. package/dist/node_modules/oidc-provider/node_modules/nanoid/index.d.ts +106 -0
  403. package/dist/node_modules/oidc-provider/node_modules/nanoid/index.js +47 -0
  404. package/dist/node_modules/oidc-provider/node_modules/nanoid/nanoid.js +1 -0
  405. package/dist/node_modules/oidc-provider/node_modules/nanoid/non-secure/index.d.ts +48 -0
  406. package/dist/node_modules/oidc-provider/node_modules/nanoid/non-secure/index.js +21 -0
  407. package/dist/node_modules/oidc-provider/node_modules/nanoid/package.json +46 -0
  408. package/dist/node_modules/oidc-provider/node_modules/nanoid/url-alphabet/index.js +2 -0
  409. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/LICENSE +21 -0
  410. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/Readme.md +224 -0
  411. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/dist/index.d.ts +144 -0
  412. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/dist/index.js +409 -0
  413. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/dist/index.js.map +1 -0
  414. package/dist/node_modules/oidc-provider/node_modules/path-to-regexp/package.json +64 -0
  415. package/dist/node_modules/oidc-provider/node_modules/statuses/HISTORY.md +87 -0
  416. package/dist/node_modules/oidc-provider/node_modules/statuses/LICENSE +23 -0
  417. package/dist/node_modules/oidc-provider/node_modules/statuses/README.md +139 -0
  418. package/dist/node_modules/oidc-provider/node_modules/statuses/codes.json +65 -0
  419. package/dist/node_modules/oidc-provider/node_modules/statuses/index.js +146 -0
  420. package/dist/node_modules/oidc-provider/node_modules/statuses/package.json +49 -0
  421. package/dist/node_modules/oidc-provider/package.json +95 -0
  422. package/dist/node_modules/quick-lru/index.d.ts +178 -0
  423. package/dist/node_modules/quick-lru/index.js +329 -0
  424. package/dist/node_modules/quick-lru/license +9 -0
  425. package/dist/node_modules/quick-lru/package.json +54 -0
  426. package/dist/node_modules/quick-lru/readme.md +236 -0
  427. package/dist/node_modules/statuses/HISTORY.md +65 -0
  428. package/dist/node_modules/statuses/LICENSE +23 -0
  429. package/dist/node_modules/statuses/README.md +127 -0
  430. package/dist/node_modules/statuses/codes.json +66 -0
  431. package/dist/node_modules/statuses/index.js +113 -0
  432. package/dist/node_modules/statuses/package.json +48 -0
  433. package/dist/server/cache-adapter.d.ts +33 -0
  434. package/dist/server/cache-adapter.js +159 -0
  435. package/dist/server/index.d.ts +10 -0
  436. package/dist/server/index.js +48 -0
  437. package/dist/server/interaction.d.ts +26 -0
  438. package/dist/server/interaction.js +172 -0
  439. package/dist/server/paths.d.ts +19 -0
  440. package/dist/server/paths.js +64 -0
  441. package/dist/server/plugin.d.ts +16 -0
  442. package/dist/server/plugin.js +108 -0
  443. package/dist/server/provider-dispatch.d.ts +32 -0
  444. package/dist/server/provider-dispatch.js +252 -0
  445. package/dist/server/service.d.ts +63 -0
  446. package/dist/server/service.js +540 -0
  447. package/dist/server/utils.d.ts +12 -0
  448. package/dist/server/utils.js +58 -0
  449. package/package.json +24 -0
  450. package/server.d.ts +2 -0
  451. package/server.js +1 -0
@@ -0,0 +1,2316 @@
1
+ 'use strict'
2
+
3
+ const { test } = require('node:test')
4
+ const { Readable, finished, pipeline } = require('node:stream')
5
+ const qs = require('node:querystring')
6
+ const fs = require('node:fs')
7
+ const zlib = require('node:zlib')
8
+ const http = require('node:http')
9
+ const eos = require('end-of-stream')
10
+ const express = require('express')
11
+ const multer = require('multer')
12
+
13
+ const inject = require('../index')
14
+ const parseURL = require('../lib/parse-url')
15
+
16
+ const NpmFormData = require('form-data')
17
+ const formAutoContent = require('form-auto-content')
18
+ const httpMethods = [
19
+ 'delete',
20
+ 'get',
21
+ 'head',
22
+ 'options',
23
+ 'patch',
24
+ 'post',
25
+ 'put',
26
+ 'trace'
27
+ ]
28
+
29
+ test('returns non-chunked payload', (t, done) => {
30
+ t.plan(7)
31
+ const output = 'example.com:8080|/hello'
32
+
33
+ const dispatch = function (req, res) {
34
+ res.statusMessage = 'Super'
35
+ res.setHeader('x-extra', 'hello')
36
+ res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': output.length })
37
+ res.end(req.headers.host + '|' + req.url)
38
+ }
39
+
40
+ inject(dispatch, 'http://example.com:8080/hello', (err, res) => {
41
+ t.assert.ifError(err)
42
+ t.assert.strictEqual(res.statusCode, 200)
43
+ t.assert.strictEqual(res.statusMessage, 'Super')
44
+ t.assert.ok(res.headers.date)
45
+ t.assert.deepStrictEqual(res.headers, {
46
+ date: res.headers.date,
47
+ connection: 'keep-alive',
48
+ 'x-extra': 'hello',
49
+ 'content-type': 'text/plain',
50
+ 'content-length': output.length.toString()
51
+ })
52
+ t.assert.strictEqual(res.payload, output)
53
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|/hello')
54
+ done()
55
+ })
56
+ })
57
+
58
+ test('returns single buffer payload', (t, done) => {
59
+ t.plan(6)
60
+ const dispatch = function (req, res) {
61
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
62
+ res.end(req.headers.host + '|' + req.url)
63
+ }
64
+
65
+ inject(dispatch, { url: 'http://example.com:8080/hello' }, (err, res) => {
66
+ t.assert.ifError(err)
67
+ t.assert.ok(res.headers.date)
68
+ t.assert.ok(res.headers.connection)
69
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
70
+ t.assert.strictEqual(res.payload, 'example.com:8080|/hello')
71
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|/hello')
72
+ done()
73
+ })
74
+ })
75
+
76
+ test('passes headers', (t, done) => {
77
+ t.plan(2)
78
+ const dispatch = function (req, res) {
79
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
80
+ res.end(req.headers.super)
81
+ }
82
+
83
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', headers: { Super: 'duper' } }, (err, res) => {
84
+ t.assert.ifError(err)
85
+ t.assert.strictEqual(res.payload, 'duper')
86
+ done()
87
+ })
88
+ })
89
+
90
+ test('request has rawHeaders', (t, done) => {
91
+ t.plan(3)
92
+ const dispatch = function (req, res) {
93
+ t.assert.ok(Array.isArray(req.rawHeaders))
94
+ t.assert.deepStrictEqual(req.rawHeaders, ['super', 'duper', 'user-agent', 'lightMyRequest', 'host', 'example.com:8080'])
95
+ res.writeHead(200)
96
+ res.end()
97
+ }
98
+
99
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', headers: { Super: 'duper' } }, (err) => {
100
+ t.assert.ifError(err)
101
+ done()
102
+ })
103
+ })
104
+
105
+ test('request inherits from custom class', (t, done) => {
106
+ t.plan(2)
107
+ const dispatch = function (req, res) {
108
+ t.assert.ok(req instanceof http.IncomingMessage)
109
+ res.writeHead(200)
110
+ res.end()
111
+ }
112
+
113
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: http.IncomingMessage }, (err) => {
114
+ t.assert.ifError(err)
115
+ done()
116
+ })
117
+ })
118
+
119
+ test('request with custom class preserves stream data', (t, done) => {
120
+ t.plan(2)
121
+ const dispatch = function (req, res) {
122
+ t.assert.ok(req._readableState)
123
+ res.writeHead(200)
124
+ res.end()
125
+ }
126
+
127
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: http.IncomingMessage }, (err) => {
128
+ t.assert.ifError(err)
129
+ done()
130
+ })
131
+ })
132
+
133
+ test('assert Request option has a valid prototype', (t) => {
134
+ t.plan(2)
135
+ const dispatch = function (_req, res) {
136
+ t.assert.ifError('should not get here')
137
+ res.writeHead(500)
138
+ res.end()
139
+ }
140
+
141
+ const MyInvalidRequest = {}
142
+
143
+ t.assert.throws(() => {
144
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: MyInvalidRequest }, () => {})
145
+ }, Error)
146
+
147
+ t.assert.throws(() => {
148
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', Request: 'InvalidRequest' }, () => {})
149
+ }, Error)
150
+ })
151
+
152
+ test('passes remote address', (t, done) => {
153
+ t.plan(2)
154
+ const dispatch = function (req, res) {
155
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
156
+ res.end(req.socket.remoteAddress)
157
+ }
158
+
159
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', remoteAddress: '1.2.3.4' }, (err, res) => {
160
+ t.assert.ifError(err)
161
+ t.assert.strictEqual(res.payload, '1.2.3.4')
162
+ done()
163
+ })
164
+ })
165
+
166
+ test('passes a socket which emits events like a normal one does', (t, done) => {
167
+ t.plan(2)
168
+ const dispatch = function (req, res) {
169
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
170
+ req.socket.on('timeout', () => {})
171
+ res.end('added')
172
+ }
173
+
174
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
175
+ t.assert.ifError(err)
176
+ t.assert.strictEqual(res.payload, 'added')
177
+ done()
178
+ })
179
+ })
180
+
181
+ test('includes deprecated connection on request', (t, done) => {
182
+ t.plan(3)
183
+ const warnings = process.listeners('warning')
184
+ process.removeAllListeners('warning')
185
+ function onWarning (err) {
186
+ t.assert.strictEqual(err.code, 'FST_LIGHTMYREQUEST_DEP01')
187
+ return false
188
+ }
189
+ process.on('warning', onWarning)
190
+ t.after(() => {
191
+ process.removeListener('warning', onWarning)
192
+ for (const fn of warnings) {
193
+ process.on('warning', fn)
194
+ }
195
+ })
196
+ const dispatch = function (req, res) {
197
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
198
+ res.end(req.connection.remoteAddress)
199
+ }
200
+
201
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', remoteAddress: '1.2.3.4' }, (err, res) => {
202
+ t.assert.ifError(err)
203
+ t.assert.strictEqual(res.payload, '1.2.3.4')
204
+ done()
205
+ })
206
+ })
207
+
208
+ const parseQuery = url => {
209
+ const parsedURL = parseURL(url)
210
+ return qs.parse(parsedURL.search.slice(1))
211
+ }
212
+
213
+ test('passes query', (t, done) => {
214
+ t.plan(2)
215
+
216
+ const query = {
217
+ message: 'OK',
218
+ xs: ['foo', 'bar']
219
+ }
220
+
221
+ const dispatch = function (req, res) {
222
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
223
+ res.end(req.url)
224
+ }
225
+
226
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', query }, (err, res) => {
227
+ t.assert.ifError(err)
228
+ t.assert.deepEqual(parseQuery(res.payload), query)
229
+ done()
230
+ })
231
+ })
232
+
233
+ test('query will be merged into that in url', (t, done) => {
234
+ t.plan(2)
235
+
236
+ const query = {
237
+ xs: ['foo', 'bar']
238
+ }
239
+
240
+ const dispatch = function (req, res) {
241
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
242
+ res.end(req.url)
243
+ }
244
+
245
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello?message=OK', query }, (err, res) => {
246
+ t.assert.ifError(err)
247
+ t.assert.deepEqual(parseQuery(res.payload), Object.assign({ message: 'OK' }, query))
248
+ done()
249
+ })
250
+ })
251
+
252
+ test('passes query as a string', (t, done) => {
253
+ t.plan(2)
254
+
255
+ const query = 'message=OK&xs=foo&xs=bar'
256
+
257
+ const dispatch = function (req, res) {
258
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
259
+ res.end(req.url)
260
+ }
261
+
262
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', query }, (err, res) => {
263
+ t.assert.ifError(err)
264
+ t.assert.deepEqual(parseQuery(res.payload), {
265
+ message: 'OK',
266
+ xs: ['foo', 'bar']
267
+ })
268
+ done()
269
+ })
270
+ })
271
+
272
+ test('query as a string will be merged into that in url', (t, done) => {
273
+ t.plan(2)
274
+
275
+ const query = 'xs=foo&xs=bar'
276
+
277
+ const dispatch = function (req, res) {
278
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
279
+ res.end(req.url)
280
+ }
281
+
282
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello?message=OK', query }, (err, res) => {
283
+ t.assert.ifError(err)
284
+ t.assert.deepEqual(parseQuery(res.payload), Object.assign({ message: 'OK' }, {
285
+ xs: ['foo', 'bar']
286
+ }))
287
+ done()
288
+ })
289
+ })
290
+
291
+ test('passes localhost as default remote address', (t, done) => {
292
+ t.plan(2)
293
+ const dispatch = function (req, res) {
294
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
295
+ res.end(req.socket.remoteAddress)
296
+ }
297
+
298
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
299
+ t.assert.ifError(err)
300
+ t.assert.strictEqual(res.payload, '127.0.0.1')
301
+ done()
302
+ })
303
+ })
304
+
305
+ test('passes host option as host header', (t, done) => {
306
+ t.plan(2)
307
+ const dispatch = function (req, res) {
308
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
309
+ res.end(req.headers.host)
310
+ }
311
+
312
+ inject(dispatch, { method: 'GET', url: '/hello', headers: { host: 'test.example.com' } }, (err, res) => {
313
+ t.assert.ifError(err)
314
+ t.assert.strictEqual(res.payload, 'test.example.com')
315
+ done()
316
+ })
317
+ })
318
+
319
+ test('passes localhost as default host header', (t, done) => {
320
+ t.plan(2)
321
+ const dispatch = function (req, res) {
322
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
323
+ res.end(req.headers.host)
324
+ }
325
+
326
+ inject(dispatch, { method: 'GET', url: '/hello' }, (err, res) => {
327
+ t.assert.ifError(err)
328
+ t.assert.strictEqual(res.payload, 'localhost:80')
329
+ done()
330
+ })
331
+ })
332
+
333
+ test('passes authority as host header', (t, done) => {
334
+ t.plan(2)
335
+ const dispatch = function (req, res) {
336
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
337
+ res.end(req.headers.host)
338
+ }
339
+
340
+ inject(dispatch, { method: 'GET', url: '/hello', authority: 'something' }, (err, res) => {
341
+ t.assert.ifError(err)
342
+ t.assert.strictEqual(res.payload, 'something')
343
+ done()
344
+ })
345
+ })
346
+
347
+ test('passes uri host as host header', (t, done) => {
348
+ t.plan(2)
349
+ const dispatch = function (req, res) {
350
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
351
+ res.end(req.headers.host)
352
+ }
353
+
354
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
355
+ t.assert.ifError(err)
356
+ t.assert.strictEqual(res.payload, 'example.com:8080')
357
+ done()
358
+ })
359
+ })
360
+
361
+ test('includes default http port in host header', (t, done) => {
362
+ t.plan(2)
363
+ const dispatch = function (req, res) {
364
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
365
+ res.end(req.headers.host)
366
+ }
367
+
368
+ inject(dispatch, 'http://example.com', (err, res) => {
369
+ t.assert.ifError(err)
370
+ t.assert.strictEqual(res.payload, 'example.com:80')
371
+ done()
372
+ })
373
+ })
374
+
375
+ test('includes default https port in host header', (t, done) => {
376
+ t.plan(2)
377
+ const dispatch = function (req, res) {
378
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
379
+ res.end(req.headers.host)
380
+ }
381
+
382
+ inject(dispatch, 'https://example.com', (err, res) => {
383
+ t.assert.ifError(err)
384
+ t.assert.strictEqual(res.payload, 'example.com:443')
385
+ done()
386
+ })
387
+ })
388
+
389
+ test('optionally accepts an object as url', (t, done) => {
390
+ t.plan(5)
391
+ const output = 'example.com:8080|/hello?test=1234'
392
+
393
+ const dispatch = function (req, res) {
394
+ res.writeHead(200, { 'Content-Type': 'text/plain', 'Content-Length': output.length })
395
+ res.end(req.headers.host + '|' + req.url)
396
+ }
397
+
398
+ const url = {
399
+ protocol: 'http',
400
+ hostname: 'example.com',
401
+ port: '8080',
402
+ pathname: 'hello',
403
+ query: {
404
+ test: '1234'
405
+ }
406
+ }
407
+
408
+ inject(dispatch, { url }, (err, res) => {
409
+ t.assert.ifError(err)
410
+ t.assert.ok(res.headers.date)
411
+ t.assert.ok(res.headers.connection)
412
+ t.assert.ifError(res.headers['transfer-encoding'])
413
+ t.assert.strictEqual(res.payload, output)
414
+ done()
415
+ })
416
+ })
417
+
418
+ test('leaves user-agent unmodified', (t, done) => {
419
+ t.plan(2)
420
+ const dispatch = function (req, res) {
421
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
422
+ res.end(req.headers['user-agent'])
423
+ }
424
+
425
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', headers: { 'user-agent': 'duper' } }, (err, res) => {
426
+ t.assert.ifError(err)
427
+ t.assert.strictEqual(res.payload, 'duper')
428
+ done()
429
+ })
430
+ })
431
+
432
+ test('returns chunked payload', (t, done) => {
433
+ t.plan(5)
434
+ const dispatch = function (_req, res) {
435
+ res.writeHead(200, 'OK')
436
+ res.write('a')
437
+ res.write('b')
438
+ res.end()
439
+ }
440
+
441
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
442
+ t.assert.ifError(err)
443
+ t.assert.ok(res.headers.date)
444
+ t.assert.ok(res.headers.connection)
445
+ t.assert.strictEqual(res.headers['transfer-encoding'], 'chunked')
446
+ t.assert.strictEqual(res.payload, 'ab')
447
+ done()
448
+ })
449
+ })
450
+
451
+ test('sets trailers in response object', (t, done) => {
452
+ t.plan(4)
453
+ const dispatch = function (_req, res) {
454
+ res.setHeader('Trailer', 'Test')
455
+ res.addTrailers({ Test: 123 })
456
+ res.end()
457
+ }
458
+
459
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
460
+ t.assert.ifError(err)
461
+ t.assert.strictEqual(res.headers.trailer, 'Test')
462
+ t.assert.strictEqual(res.headers.test, undefined)
463
+ t.assert.strictEqual(res.trailers.test, '123')
464
+ done()
465
+ })
466
+ })
467
+
468
+ test('parses zipped payload', (t, done) => {
469
+ t.plan(4)
470
+ const dispatch = function (_req, res) {
471
+ res.writeHead(200, 'OK')
472
+ const stream = fs.createReadStream('./package.json')
473
+ stream.pipe(zlib.createGzip()).pipe(res)
474
+ }
475
+
476
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
477
+ t.assert.ifError(err)
478
+ fs.readFile('./package.json', { encoding: 'utf-8' }, (err, file) => {
479
+ t.assert.ifError(err)
480
+
481
+ zlib.unzip(res.rawPayload, (err, unzipped) => {
482
+ t.assert.ifError(err)
483
+ t.assert.strictEqual(unzipped.toString('utf-8'), file)
484
+ done()
485
+ })
486
+ })
487
+ })
488
+ })
489
+
490
+ test('returns multi buffer payload', (t, done) => {
491
+ t.plan(2)
492
+ const dispatch = function (_req, res) {
493
+ res.writeHead(200)
494
+ res.write('a')
495
+ res.write(Buffer.from('b'))
496
+ res.end()
497
+ }
498
+
499
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
500
+ t.assert.ifError(err)
501
+ t.assert.strictEqual(res.payload, 'ab')
502
+ done()
503
+ })
504
+ })
505
+
506
+ test('returns null payload', (t, done) => {
507
+ t.plan(2)
508
+ const dispatch = function (_req, res) {
509
+ res.writeHead(200, { 'Content-Length': 0 })
510
+ res.end()
511
+ }
512
+
513
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
514
+ t.assert.ifError(err)
515
+ t.assert.strictEqual(res.payload, '')
516
+ done()
517
+ })
518
+ })
519
+
520
+ test('allows ending twice', (t, done) => {
521
+ t.plan(2)
522
+ const dispatch = function (_req, res) {
523
+ res.writeHead(200, { 'Content-Length': 0 })
524
+ res.end()
525
+ res.end()
526
+ }
527
+
528
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
529
+ t.assert.ifError(err)
530
+ t.assert.strictEqual(res.payload, '')
531
+ done()
532
+ })
533
+ })
534
+
535
+ test('identifies injection object', (t, done) => {
536
+ t.plan(6)
537
+ const dispatchRequest = function (req, res) {
538
+ t.assert.strictEqual(inject.isInjection(req), true)
539
+ t.assert.strictEqual(inject.isInjection(res), true)
540
+
541
+ res.writeHead(200, { 'Content-Length': 0 })
542
+ res.end()
543
+ }
544
+
545
+ const dispatchCustomRequest = function (req, res) {
546
+ t.assert.strictEqual(inject.isInjection(req), true)
547
+ t.assert.strictEqual(inject.isInjection(res), true)
548
+
549
+ res.writeHead(200, { 'Content-Length': 0 })
550
+ res.end()
551
+ }
552
+
553
+ const options = { method: 'GET', url: '/' }
554
+ const cb = (err) => { t.assert.ifError(err) }
555
+ const cbDone = (err) => {
556
+ t.assert.ifError(err)
557
+ done()
558
+ }
559
+
560
+ inject(dispatchRequest, options, cb)
561
+ inject(dispatchCustomRequest, { ...options, Request: http.IncomingMessage }, cbDone)
562
+ })
563
+
564
+ test('pipes response', (t, done) => {
565
+ t.plan(3)
566
+ let finished = false
567
+ const dispatch = function (_req, res) {
568
+ res.writeHead(200)
569
+ const stream = getTestStream()
570
+
571
+ res.on('finish', () => {
572
+ finished = true
573
+ })
574
+
575
+ stream.pipe(res)
576
+ }
577
+
578
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
579
+ t.assert.ifError(err)
580
+ t.assert.strictEqual(finished, true)
581
+ t.assert.strictEqual(res.payload, 'hi')
582
+ done()
583
+ })
584
+ })
585
+
586
+ test('pipes response with old stream', (t, done) => {
587
+ t.plan(3)
588
+ let finished = false
589
+ const dispatch = function (_req, res) {
590
+ res.writeHead(200)
591
+ const stream = getTestStream()
592
+ stream.pause()
593
+ const stream2 = new Readable().wrap(stream)
594
+ stream.resume()
595
+
596
+ res.on('finish', () => {
597
+ finished = true
598
+ })
599
+
600
+ stream2.pipe(res)
601
+ }
602
+
603
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
604
+ t.assert.ifError(err)
605
+ t.assert.strictEqual(finished, true)
606
+ t.assert.strictEqual(res.payload, 'hi')
607
+ done()
608
+ })
609
+ })
610
+
611
+ test('echos object payload', (t, done) => {
612
+ t.plan(3)
613
+ const dispatch = function (req, res) {
614
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
615
+ req.pipe(res)
616
+ }
617
+
618
+ inject(dispatch, { method: 'POST', url: '/test', payload: { a: 1 } }, (err, res) => {
619
+ t.assert.ifError(err)
620
+ t.assert.strictEqual(res.headers['content-type'], 'application/json')
621
+ t.assert.strictEqual(res.payload, '{"a":1}')
622
+ done()
623
+ })
624
+ })
625
+
626
+ test('supports body option in Request and property in Response', (t, done) => {
627
+ t.plan(3)
628
+ const dispatch = function (req, res) {
629
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
630
+ req.pipe(res)
631
+ }
632
+
633
+ inject(dispatch, { method: 'POST', url: '/test', body: { a: 1 } }, (err, res) => {
634
+ t.assert.ifError(err)
635
+ t.assert.strictEqual(res.headers['content-type'], 'application/json')
636
+ t.assert.strictEqual(res.body, '{"a":1}')
637
+ done()
638
+ })
639
+ })
640
+
641
+ test('echos buffer payload', (t, done) => {
642
+ t.plan(2)
643
+ const dispatch = function (req, res) {
644
+ res.writeHead(200)
645
+ req.pipe(res)
646
+ }
647
+
648
+ inject(dispatch, { method: 'POST', url: '/test', payload: Buffer.from('test!') }, (err, res) => {
649
+ t.assert.ifError(err)
650
+ t.assert.strictEqual(res.payload, 'test!')
651
+ done()
652
+ })
653
+ })
654
+
655
+ test('echos object payload with non-english utf-8 string', (t, done) => {
656
+ t.plan(3)
657
+ const dispatch = function (req, res) {
658
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
659
+ req.pipe(res)
660
+ }
661
+
662
+ inject(dispatch, { method: 'POST', url: '/test', payload: { a: '½½א' } }, (err, res) => {
663
+ t.assert.ifError(err)
664
+ t.assert.strictEqual(res.headers['content-type'], 'application/json')
665
+ t.assert.strictEqual(res.payload, '{"a":"½½א"}')
666
+ done()
667
+ })
668
+ })
669
+
670
+ test('echos object payload without payload', (t, done) => {
671
+ t.plan(2)
672
+ const dispatch = function (req, res) {
673
+ res.writeHead(200)
674
+ req.pipe(res)
675
+ }
676
+
677
+ inject(dispatch, { method: 'POST', url: '/test' }, (err, res) => {
678
+ t.assert.ifError(err)
679
+ t.assert.strictEqual(res.payload, '')
680
+ done()
681
+ })
682
+ })
683
+
684
+ test('retains content-type header', (t, done) => {
685
+ t.plan(3)
686
+ const dispatch = function (req, res) {
687
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
688
+ req.pipe(res)
689
+ }
690
+
691
+ inject(dispatch, { method: 'POST', url: '/test', payload: { a: 1 }, headers: { 'content-type': 'something' } }, (err, res) => {
692
+ t.assert.ifError(err)
693
+ t.assert.strictEqual(res.headers['content-type'], 'something')
694
+ t.assert.strictEqual(res.payload, '{"a":1}')
695
+ done()
696
+ })
697
+ })
698
+
699
+ test('adds a content-length header if none set when payload specified', (t, done) => {
700
+ t.plan(2)
701
+ const dispatch = function (req, res) {
702
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
703
+ res.end(req.headers['content-length'])
704
+ }
705
+
706
+ inject(dispatch, { method: 'POST', url: '/test', payload: { a: 1 } }, (err, res) => {
707
+ t.assert.ifError(err)
708
+ t.assert.strictEqual(res.payload, '{"a":1}'.length.toString())
709
+ done()
710
+ })
711
+ })
712
+
713
+ test('retains a content-length header when payload specified', (t, done) => {
714
+ t.plan(2)
715
+ const dispatch = function (req, res) {
716
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
717
+ res.end(req.headers['content-length'])
718
+ }
719
+
720
+ inject(dispatch, { method: 'POST', url: '/test', payload: '', headers: { 'content-length': '10' } }, (err, res) => {
721
+ t.assert.ifError(err)
722
+ t.assert.strictEqual(res.payload, '10')
723
+ done()
724
+ })
725
+ })
726
+
727
+ test('can handle a stream payload', (t, done) => {
728
+ t.plan(2)
729
+ const dispatch = function (req, res) {
730
+ readStream(req, (buff) => {
731
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
732
+ res.end(buff)
733
+ })
734
+ }
735
+
736
+ inject(dispatch, { method: 'POST', url: '/', payload: getTestStream() }, (err, res) => {
737
+ t.assert.ifError(err)
738
+ t.assert.strictEqual(res.payload, 'hi')
739
+ done()
740
+ })
741
+ })
742
+
743
+ test('can handle a stream payload that errors', (t, done) => {
744
+ t.plan(2)
745
+ const dispatch = function (req) {
746
+ req.resume()
747
+ }
748
+
749
+ const payload = new Readable({
750
+ read () {
751
+ this.destroy(new Error('kaboom'))
752
+ }
753
+ })
754
+
755
+ inject(dispatch, { method: 'POST', url: '/', payload }, (err) => {
756
+ t.assert.ok(err)
757
+ t.assert.equal(err.message, 'kaboom')
758
+ done()
759
+ })
760
+ })
761
+
762
+ test('can handle a stream payload of utf-8 strings', (t, done) => {
763
+ t.plan(2)
764
+ const dispatch = function (req, res) {
765
+ readStream(req, (buff) => {
766
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
767
+ res.end(buff)
768
+ })
769
+ }
770
+
771
+ inject(dispatch, { method: 'POST', url: '/', payload: getTestStream('utf8') }, (err, res) => {
772
+ t.assert.ifError(err)
773
+ t.assert.strictEqual(res.payload, 'hi')
774
+ done()
775
+ })
776
+ })
777
+
778
+ test('can override stream payload content-length header', (t, done) => {
779
+ t.plan(2)
780
+ const dispatch = function (req, res) {
781
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
782
+ res.end(req.headers['content-length'])
783
+ }
784
+
785
+ const headers = { 'content-length': '100' }
786
+
787
+ inject(dispatch, { method: 'POST', url: '/', payload: getTestStream(), headers }, (err, res) => {
788
+ t.assert.ifError(err)
789
+ t.assert.strictEqual(res.payload, '100')
790
+ done()
791
+ })
792
+ })
793
+
794
+ test('writeHead returns single buffer payload', (t, done) => {
795
+ t.plan(4)
796
+ const reply = 'Hello World'
797
+ const statusCode = 200
798
+ const statusMessage = 'OK'
799
+ const dispatch = function (_req, res) {
800
+ res.writeHead(statusCode, statusMessage, { 'Content-Type': 'text/plain', 'Content-Length': reply.length })
801
+ res.end(reply)
802
+ }
803
+
804
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
805
+ t.assert.ifError(err)
806
+ t.assert.strictEqual(res.statusCode, statusCode)
807
+ t.assert.strictEqual(res.statusMessage, statusMessage)
808
+ t.assert.strictEqual(res.payload, reply)
809
+ done()
810
+ })
811
+ })
812
+
813
+ test('_read() plays payload', (t, done) => {
814
+ t.plan(2)
815
+ const dispatch = function (req, res) {
816
+ let buffer = ''
817
+ req.on('readable', () => {
818
+ buffer = buffer + (req.read() || '')
819
+ })
820
+
821
+ req.on('close', () => {
822
+ })
823
+
824
+ req.on('end', () => {
825
+ res.writeHead(200, { 'Content-Length': 0 })
826
+ res.end(buffer)
827
+ req.destroy()
828
+ })
829
+ }
830
+
831
+ const body = 'something special just for you'
832
+ inject(dispatch, { method: 'GET', url: '/', payload: body }, (err, res) => {
833
+ t.assert.ifError(err)
834
+ t.assert.strictEqual(res.payload, body)
835
+ done()
836
+ })
837
+ })
838
+
839
+ test('simulates split', (t, done) => {
840
+ t.plan(2)
841
+ const dispatch = function (req, res) {
842
+ let buffer = ''
843
+ req.on('readable', () => {
844
+ buffer = buffer + (req.read() || '')
845
+ })
846
+
847
+ req.on('close', () => {
848
+ })
849
+
850
+ req.on('end', () => {
851
+ res.writeHead(200, { 'Content-Length': 0 })
852
+ res.end(buffer)
853
+ req.destroy()
854
+ })
855
+ }
856
+
857
+ const body = 'something special just for you'
858
+ inject(dispatch, { method: 'GET', url: '/', payload: body, simulate: { split: true } }, (err, res) => {
859
+ t.assert.ifError(err)
860
+ t.assert.strictEqual(res.payload, body)
861
+ done()
862
+ })
863
+ })
864
+
865
+ test('simulates error', (t, done) => {
866
+ t.plan(2)
867
+ const dispatch = function (req, res) {
868
+ req.on('readable', () => {
869
+ })
870
+
871
+ req.on('error', () => {
872
+ res.writeHead(200, { 'Content-Length': 0 })
873
+ res.end('error')
874
+ })
875
+ }
876
+
877
+ const body = 'something special just for you'
878
+ inject(dispatch, { method: 'GET', url: '/', payload: body, simulate: { error: true } }, (err, res) => {
879
+ t.assert.ifError(err)
880
+ t.assert.strictEqual(res.payload, 'error')
881
+ done()
882
+ })
883
+ })
884
+
885
+ test('simulates no end without payload', (t, done) => {
886
+ t.plan(2)
887
+ let end = false
888
+ const dispatch = function (req) {
889
+ req.resume()
890
+ req.on('end', () => {
891
+ end = true
892
+ })
893
+ }
894
+
895
+ let replied = false
896
+ inject(dispatch, { method: 'GET', url: '/', simulate: { end: false } }, () => {
897
+ replied = true
898
+ })
899
+
900
+ setTimeout(() => {
901
+ t.assert.strictEqual(end, false)
902
+ t.assert.strictEqual(replied, false)
903
+ done()
904
+ }, 10)
905
+ })
906
+
907
+ test('simulates no end with payload', (t, done) => {
908
+ t.plan(2)
909
+ let end = false
910
+ const dispatch = function (req) {
911
+ req.resume()
912
+ req.on('end', () => {
913
+ end = true
914
+ })
915
+ }
916
+
917
+ let replied = false
918
+ inject(dispatch, { method: 'GET', url: '/', payload: '1234567', simulate: { end: false } }, () => {
919
+ replied = true
920
+ })
921
+
922
+ setTimeout(() => {
923
+ t.assert.strictEqual(end, false)
924
+ t.assert.strictEqual(replied, false)
925
+ done()
926
+ }, 10)
927
+ })
928
+
929
+ test('simulates close', (t, done) => {
930
+ t.plan(2)
931
+ const dispatch = function (req, res) {
932
+ let buffer = ''
933
+ req.on('readable', () => {
934
+ buffer = buffer + (req.read() || '')
935
+ })
936
+
937
+ req.on('close', () => {
938
+ res.writeHead(200, { 'Content-Length': 0 })
939
+ res.end('close')
940
+ })
941
+
942
+ req.on('end', () => {
943
+ })
944
+ }
945
+
946
+ const body = 'something special just for you'
947
+ inject(dispatch, { method: 'GET', url: '/', payload: body, simulate: { close: true } }, (err, res) => {
948
+ t.assert.ifError(err)
949
+ t.assert.strictEqual(res.payload, 'close')
950
+ done()
951
+ })
952
+ })
953
+
954
+ test('errors for invalid input options', (t) => {
955
+ t.plan(1)
956
+
957
+ t.assert.throws(
958
+ () => inject({}, {}, () => {}),
959
+ { name: 'AssertionError', message: 'dispatchFunc should be a function' }
960
+ )
961
+ })
962
+
963
+ test('errors for missing url', (t) => {
964
+ t.plan(1)
965
+
966
+ t.assert.throws(
967
+ () => inject(() => {}, {}, () => {}),
968
+ { message: /must have required property 'url'/ }
969
+ )
970
+ })
971
+
972
+ test('errors for an incorrect simulation object', (t) => {
973
+ t.plan(1)
974
+
975
+ t.assert.throws(
976
+ () => inject(() => {}, { url: '/', simulate: 'sample string' }, () => {}),
977
+ { message: /^must be object$/ }
978
+ )
979
+ })
980
+
981
+ test('ignores incorrect simulation object', (t) => {
982
+ t.plan(1)
983
+
984
+ t.assert.doesNotThrow(() => inject(() => { }, { url: '/', simulate: 'sample string', validate: false }, () => { }))
985
+ })
986
+
987
+ test('errors for an incorrect simulation object values', (t) => {
988
+ t.plan(1)
989
+
990
+ t.assert.throws(
991
+ () => inject(() => {}, { url: '/', simulate: { end: 'wrong input' } }, () => {}),
992
+ { message: /^must be boolean$/ }
993
+ )
994
+ })
995
+
996
+ test('promises support', (t, done) => {
997
+ t.plan(1)
998
+ const dispatch = function (_req, res) {
999
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1000
+ res.end('hello')
1001
+ }
1002
+
1003
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' })
1004
+ .then(res => {
1005
+ t.assert.strictEqual(res.payload, 'hello')
1006
+ done()
1007
+ })
1008
+ .catch(t.assert.fail)
1009
+ })
1010
+
1011
+ test('this should be the server instance', (t, done) => {
1012
+ t.plan(2)
1013
+
1014
+ const server = http.createServer()
1015
+
1016
+ const dispatch = function (_req, res) {
1017
+ t.assert.strictEqual(this, server)
1018
+ res.end('hello')
1019
+ }
1020
+
1021
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', server })
1022
+ .then(res => t.assert.strictEqual(res.statusCode, 200))
1023
+ .catch(t.assert.fail)
1024
+ .finally(done)
1025
+ })
1026
+
1027
+ test('should handle response errors', (t, done) => {
1028
+ t.plan(1)
1029
+ const dispatch = function (_req, res) {
1030
+ res.connection.destroy(new Error('kaboom'))
1031
+ }
1032
+
1033
+ inject(dispatch, 'http://example.com:8080/hello', (err) => {
1034
+ t.assert.ok(err)
1035
+ done()
1036
+ })
1037
+ })
1038
+
1039
+ test('should handle response errors (promises)', async (t) => {
1040
+ t.plan(1)
1041
+ const dispatch = function (_req, res) {
1042
+ res.connection.destroy(new Error('kaboom'))
1043
+ }
1044
+
1045
+ await t.assert.rejects(
1046
+ () => inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello' }),
1047
+ { name: 'Error', message: 'kaboom' }
1048
+ )
1049
+ })
1050
+
1051
+ test('should handle response timeout handler', (t, done) => {
1052
+ t.plan(3)
1053
+ const dispatch = function (_req, res) {
1054
+ const handle = setTimeout(() => {
1055
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1056
+ res.end('incorrect')
1057
+ }, 200)
1058
+ res.setTimeout(100, () => {
1059
+ clearTimeout(handle)
1060
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1061
+ res.end('correct')
1062
+ })
1063
+ res.on('timeout', () => {
1064
+ t.assert.ok(true, 'Response timeout event not emitted')
1065
+ })
1066
+ }
1067
+ inject(dispatch, { method: 'GET', url: '/test' }, (err, res) => {
1068
+ t.assert.ifError(err)
1069
+ t.assert.strictEqual(res.payload, 'correct')
1070
+ done()
1071
+ })
1072
+ })
1073
+
1074
+ test('should throw on unknown HTTP method', (t) => {
1075
+ t.plan(1)
1076
+ const dispatch = function () { }
1077
+
1078
+ t.assert.throws(() => inject(dispatch, { method: 'UNKNOWN_METHOD', url: 'http://example.com:8080/hello' }, (err, _res) => {
1079
+ t.assert.ok(err)
1080
+ }), Error)
1081
+ })
1082
+
1083
+ test('should throw on unknown HTTP method (promises)', (t) => {
1084
+ t.plan(1)
1085
+ const dispatch = function () { }
1086
+
1087
+ t.assert.throws(() => inject(dispatch, { method: 'UNKNOWN_METHOD', url: 'http://example.com:8080/hello' })
1088
+ .then(() => {}), Error)
1089
+ })
1090
+
1091
+ test('HTTP method is case insensitive', (t, done) => {
1092
+ t.plan(3)
1093
+
1094
+ const dispatch = function (_req, res) {
1095
+ res.end('Hi!')
1096
+ }
1097
+
1098
+ inject(dispatch, { method: 'get', url: 'http://example.com:8080/hello' }, (err, res) => {
1099
+ t.assert.ifError(err)
1100
+ t.assert.strictEqual(res.statusCode, 200)
1101
+ t.assert.strictEqual(res.payload, 'Hi!')
1102
+ done()
1103
+ })
1104
+ })
1105
+
1106
+ test('form-data should be handled correctly', (t, done) => {
1107
+ t.plan(4)
1108
+
1109
+ const dispatch = function (req, res) {
1110
+ t.assert.strictEqual(req.headers['transfer-encoding'], undefined)
1111
+ let body = ''
1112
+ req.on('data', d => {
1113
+ body += d
1114
+ })
1115
+ req.on('end', () => {
1116
+ res.end(body)
1117
+ })
1118
+ }
1119
+
1120
+ const form = new NpmFormData()
1121
+ form.append('my_field', 'my value')
1122
+
1123
+ inject(dispatch, {
1124
+ method: 'POST',
1125
+ url: 'http://example.com:8080/hello',
1126
+ headers: {
1127
+ // Transfer-encoding is automatically deleted if Stream1 is used
1128
+ 'transfer-encoding': 'chunked'
1129
+ },
1130
+ payload: form
1131
+ }, (err, res) => {
1132
+ t.assert.ifError(err)
1133
+ t.assert.strictEqual(res.statusCode, 200)
1134
+ t.assert.ok(/--.+\r\nContent-Disposition: form-data; name="my_field"\r\n\r\nmy value\r\n--.+--\r\n/.test(res.payload))
1135
+ done()
1136
+ })
1137
+ })
1138
+
1139
+ test('path as alias to url', (t, done) => {
1140
+ t.plan(2)
1141
+
1142
+ const dispatch = function (req, res) {
1143
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1144
+ res.end(req.url)
1145
+ }
1146
+
1147
+ inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1148
+ t.assert.ifError(err)
1149
+ t.assert.strictEqual(res.payload, '/hello')
1150
+ done()
1151
+ })
1152
+ })
1153
+
1154
+ test('Should throw if both path and url are missing', (t) => {
1155
+ t.plan(1)
1156
+
1157
+ t.assert.throws(
1158
+ () => inject(() => {}, { method: 'GET' }, () => {}),
1159
+ { message: /must have required property 'url',must have required property 'path'/ }
1160
+ )
1161
+ })
1162
+
1163
+ test('chainable api: backwards compatibility for promise (then)', (t, done) => {
1164
+ t.plan(1)
1165
+
1166
+ const dispatch = function (_req, res) {
1167
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1168
+ res.end('hello')
1169
+ }
1170
+
1171
+ inject(dispatch)
1172
+ .get('/')
1173
+ .then(res => t.assert.strictEqual(res.payload, 'hello'))
1174
+ .catch(t.assert.fail)
1175
+ .finally(done)
1176
+ })
1177
+
1178
+ test('chainable api: backwards compatibility for promise (catch)', (t, done) => {
1179
+ t.plan(1)
1180
+
1181
+ function dispatch () {
1182
+ throw Error
1183
+ }
1184
+
1185
+ inject(dispatch)
1186
+ .get('/')
1187
+ .catch(err => t.assert.ok(err))
1188
+ .finally(done)
1189
+ })
1190
+
1191
+ test('chainable api: multiple call of then should return the same promise', (t, done) => {
1192
+ t.plan(2)
1193
+ let id = 0
1194
+
1195
+ function dispatch (_req, res) {
1196
+ res.writeHead(200, { 'Content-Type': 'text/plain', 'Request-Id': id })
1197
+ ++id
1198
+ t.assert.ok('request id incremented')
1199
+ res.end('hello')
1200
+ }
1201
+
1202
+ const chain = inject(dispatch).get('/')
1203
+ chain.then(res => {
1204
+ chain.then(rep => {
1205
+ t.assert.strictEqual(res.headers['request-id'], rep.headers['request-id'])
1206
+ done()
1207
+ })
1208
+ })
1209
+ })
1210
+
1211
+ test('chainable api: http methods should work correctly', (t, done) => {
1212
+ t.plan(16)
1213
+
1214
+ function dispatch (req, res) {
1215
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1216
+ res.end(req.method)
1217
+ }
1218
+
1219
+ httpMethods.forEach((method, index) => {
1220
+ inject(dispatch)[method]('http://example.com:8080/hello')
1221
+ .end((err, res) => {
1222
+ t.assert.ifError(err)
1223
+ t.assert.strictEqual(res.body, method.toUpperCase())
1224
+ if (index === httpMethods.length - 1) {
1225
+ done()
1226
+ }
1227
+ })
1228
+ })
1229
+ })
1230
+
1231
+ test('chainable api: http methods should throw if already invoked', (t, done) => {
1232
+ t.plan(8)
1233
+
1234
+ function dispatch (_req, res) {
1235
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1236
+ res.end()
1237
+ }
1238
+
1239
+ httpMethods.forEach((method, index) => {
1240
+ const chain = inject(dispatch)[method]('http://example.com:8080/hello')
1241
+ chain.end()
1242
+ t.assert.throws(() => chain[method]('/'), Error)
1243
+ if (index === httpMethods.length - 1) {
1244
+ done()
1245
+ }
1246
+ })
1247
+ })
1248
+
1249
+ test('chainable api: body method should work correctly', (t, done) => {
1250
+ t.plan(2)
1251
+
1252
+ function dispatch (req, res) {
1253
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1254
+ req.pipe(res)
1255
+ }
1256
+
1257
+ inject(dispatch)
1258
+ .get('http://example.com:8080/hello')
1259
+ .body('test')
1260
+ .end((err, res) => {
1261
+ t.assert.ifError(err)
1262
+ t.assert.strictEqual(res.body, 'test')
1263
+ done()
1264
+ })
1265
+ })
1266
+
1267
+ test('chainable api: cookie', (t, done) => {
1268
+ t.plan(2)
1269
+
1270
+ function dispatch (req, res) {
1271
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1272
+ res.end(req.headers.cookie)
1273
+ }
1274
+
1275
+ inject(dispatch)
1276
+ .get('http://example.com:8080/hello')
1277
+ .body('test')
1278
+ .cookies({ hello: 'world', fastify: 'rulez' })
1279
+ .end((err, res) => {
1280
+ t.assert.ifError(err)
1281
+ t.assert.strictEqual(res.body, 'hello=world; fastify=rulez')
1282
+ done()
1283
+ })
1284
+ })
1285
+
1286
+ test('chainable api: body method should throw if already invoked', (t) => {
1287
+ t.plan(1)
1288
+
1289
+ function dispatch (_req, res) {
1290
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1291
+ res.end()
1292
+ }
1293
+
1294
+ const chain = inject(dispatch)
1295
+ chain
1296
+ .get('http://example.com:8080/hello')
1297
+ .end()
1298
+ t.assert.throws(() => chain.body('test'), Error)
1299
+ })
1300
+
1301
+ test('chainable api: headers method should work correctly', (t, done) => {
1302
+ t.plan(2)
1303
+
1304
+ function dispatch (req, res) {
1305
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1306
+ res.end(req.headers.foo)
1307
+ }
1308
+
1309
+ inject(dispatch)
1310
+ .get('http://example.com:8080/hello')
1311
+ .headers({ foo: 'bar' })
1312
+ .end((err, res) => {
1313
+ t.assert.ifError(err)
1314
+ t.assert.strictEqual(res.payload, 'bar')
1315
+ done()
1316
+ })
1317
+ })
1318
+
1319
+ test('chainable api: headers method should throw if already invoked', (t) => {
1320
+ t.plan(1)
1321
+
1322
+ function dispatch (_req, res) {
1323
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1324
+ res.end()
1325
+ }
1326
+
1327
+ const chain = inject(dispatch)
1328
+ chain
1329
+ .get('http://example.com:8080/hello')
1330
+ .end()
1331
+ t.assert.throws(() => chain.headers({ foo: 'bar' }), Error)
1332
+ })
1333
+
1334
+ test('chainable api: payload method should work correctly', (t, done) => {
1335
+ t.plan(2)
1336
+
1337
+ function dispatch (req, res) {
1338
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1339
+ req.pipe(res)
1340
+ }
1341
+
1342
+ inject(dispatch)
1343
+ .get('http://example.com:8080/hello')
1344
+ .payload('payload')
1345
+ .end((err, res) => {
1346
+ t.assert.ifError(err)
1347
+ t.assert.strictEqual(res.payload, 'payload')
1348
+ done()
1349
+ })
1350
+ })
1351
+
1352
+ test('chainable api: payload method should throw if already invoked', (t) => {
1353
+ t.plan(1)
1354
+
1355
+ function dispatch (_req, res) {
1356
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1357
+ res.end()
1358
+ }
1359
+
1360
+ const chain = inject(dispatch)
1361
+ chain
1362
+ .get('http://example.com:8080/hello')
1363
+ .end()
1364
+ t.assert.throws(() => chain.payload('payload'), Error)
1365
+ })
1366
+
1367
+ test('chainable api: query method should work correctly', (t, done) => {
1368
+ t.plan(2)
1369
+
1370
+ const query = {
1371
+ message: 'OK',
1372
+ xs: ['foo', 'bar']
1373
+ }
1374
+
1375
+ function dispatch (req, res) {
1376
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1377
+ res.end(req.url)
1378
+ }
1379
+
1380
+ inject(dispatch)
1381
+ .get('http://example.com:8080/hello')
1382
+ .query(query)
1383
+ .end((err, res) => {
1384
+ t.assert.ifError(err)
1385
+ t.assert.deepEqual(parseQuery(res.payload), query)
1386
+ done()
1387
+ })
1388
+ })
1389
+
1390
+ test('chainable api: query method should throw if already invoked', (t) => {
1391
+ t.plan(1)
1392
+
1393
+ function dispatch (_req, res) {
1394
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1395
+ res.end()
1396
+ }
1397
+
1398
+ const chain = inject(dispatch)
1399
+ chain
1400
+ .get('http://example.com:8080/hello')
1401
+ .end()
1402
+ t.assert.throws(() => chain.query({ foo: 'bar' }), Error)
1403
+ })
1404
+
1405
+ test('chainable api: invoking end method after promise method should throw', (t) => {
1406
+ t.plan(1)
1407
+
1408
+ function dispatch (_req, res) {
1409
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1410
+ res.end()
1411
+ }
1412
+
1413
+ const chain = inject(dispatch).get('http://example.com:8080/hello')
1414
+
1415
+ chain.then()
1416
+ t.assert.throws(() => chain.end(), Error)
1417
+ })
1418
+
1419
+ test('chainable api: invoking promise method after end method with a callback function should throw', (t, done) => {
1420
+ t.plan(2)
1421
+
1422
+ function dispatch (_req, res) {
1423
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1424
+ res.end()
1425
+ }
1426
+
1427
+ const chain = inject(dispatch).get('http://example.com:8080/hello')
1428
+
1429
+ chain.end((err) => {
1430
+ t.assert.ifError(err)
1431
+ done()
1432
+ })
1433
+ t.assert.throws(() => chain.then(), Error)
1434
+ })
1435
+
1436
+ test('chainable api: invoking promise method after end method without a callback function should work properly', (t, done) => {
1437
+ t.plan(1)
1438
+
1439
+ function dispatch (_req, res) {
1440
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1441
+ res.end('hello')
1442
+ }
1443
+
1444
+ inject(dispatch)
1445
+ .get('http://example.com:8080/hello')
1446
+ .end()
1447
+ .then(res => t.assert.strictEqual(res.payload, 'hello'))
1448
+ .finally(done)
1449
+ })
1450
+
1451
+ test('chainable api: invoking end method multiple times should throw', (t) => {
1452
+ t.plan(1)
1453
+
1454
+ function dispatch (_req, res) {
1455
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1456
+ res.end()
1457
+ }
1458
+
1459
+ const chain = inject(dispatch).get('http://example.com:8080/hello')
1460
+
1461
+ chain.end()
1462
+ t.assert.throws(() => chain.end(), Error)
1463
+ })
1464
+
1465
+ test('chainable api: string url', (t, done) => {
1466
+ t.plan(2)
1467
+
1468
+ function dispatch (_req, res) {
1469
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1470
+ res.end()
1471
+ t.assert.ok('pass')
1472
+ }
1473
+
1474
+ const chain = inject(dispatch, 'http://example.com:8080/hello')
1475
+
1476
+ chain.then(() => t.assert.ok('pass')).finally(done)
1477
+ })
1478
+
1479
+ test('Response.json() should parse the JSON payload', (t, done) => {
1480
+ t.plan(2)
1481
+
1482
+ const jsonData = {
1483
+ a: 1,
1484
+ b: '2'
1485
+ }
1486
+
1487
+ const dispatch = function (_req, res) {
1488
+ res.writeHead(200, { 'Content-Type': 'application/json' })
1489
+ res.end(JSON.stringify(jsonData))
1490
+ }
1491
+
1492
+ inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1493
+ t.assert.ifError(err)
1494
+ const { json } = res
1495
+ t.assert.deepStrictEqual(json(), jsonData)
1496
+ done()
1497
+ })
1498
+ })
1499
+
1500
+ test('Response.json() should not throw an error if content-type is not application/json', (t, done) => {
1501
+ t.plan(2)
1502
+
1503
+ const jsonData = {
1504
+ a: 1,
1505
+ b: '2'
1506
+ }
1507
+
1508
+ const dispatch = function (_req, res) {
1509
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1510
+ res.end(JSON.stringify(jsonData))
1511
+ }
1512
+
1513
+ inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1514
+ t.assert.ifError(err)
1515
+ const { json } = res
1516
+ t.assert.deepStrictEqual(json(), jsonData)
1517
+ done()
1518
+ })
1519
+ })
1520
+
1521
+ test('Response.json() should throw an error if the payload is not of valid JSON format', (t, done) => {
1522
+ t.plan(2)
1523
+
1524
+ const dispatch = function (_req, res) {
1525
+ res.writeHead(200, { 'Content-Type': 'application/json' })
1526
+ res.end('notAJSON')
1527
+ }
1528
+
1529
+ inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1530
+ t.assert.ifError(err)
1531
+ t.assert.throws(res.json, Error)
1532
+ done()
1533
+ })
1534
+ })
1535
+
1536
+ test('Response.stream() should provide a Readable stream', (t, done) => {
1537
+ const lines = [
1538
+ JSON.stringify({ foo: 'bar' }),
1539
+ JSON.stringify({ hello: 'world' })
1540
+ ]
1541
+
1542
+ t.plan(2 + lines.length)
1543
+
1544
+ const dispatch = function (_req, res) {
1545
+ res.writeHead(200, { 'Content-Type': 'multiple/json' })
1546
+ for (const line of lines) {
1547
+ res.write(line)
1548
+ }
1549
+ res.end()
1550
+ }
1551
+
1552
+ inject(dispatch, { method: 'GET', path: 'http://example.com:8080/hello' }, (err, res) => {
1553
+ t.assert.ifError(err)
1554
+ const readable = res.stream()
1555
+ const payload = []
1556
+ t.assert.strictEqual(readable instanceof Readable, true)
1557
+ readable.on('data', function (chunk) {
1558
+ payload.push(chunk)
1559
+ })
1560
+ readable.on('end', function () {
1561
+ for (let i = 0; i < lines.length; i++) {
1562
+ t.assert.strictEqual(lines[i], payload[i].toString())
1563
+ }
1564
+ done()
1565
+ })
1566
+ })
1567
+ })
1568
+
1569
+ test('promise api should auto start (fire and forget)', (t, done) => {
1570
+ t.plan(1)
1571
+
1572
+ function dispatch (_req, res) {
1573
+ t.assert.ok('dispatch called')
1574
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1575
+ res.end()
1576
+ }
1577
+
1578
+ inject(dispatch, 'http://example.com:8080/hello')
1579
+ process.nextTick(done)
1580
+ })
1581
+
1582
+ test('disabling autostart', (t, done) => {
1583
+ t.plan(3)
1584
+
1585
+ let called = false
1586
+
1587
+ function dispatch (_req, res) {
1588
+ t.assert.ok('dispatch called')
1589
+ called = true
1590
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1591
+ res.end()
1592
+ done()
1593
+ }
1594
+
1595
+ const p = inject(dispatch, {
1596
+ url: 'http://example.com:8080/hello',
1597
+ autoStart: false
1598
+ })
1599
+
1600
+ setImmediate(() => {
1601
+ t.assert.strictEqual(called, false)
1602
+ p.then(() => {
1603
+ t.assert.strictEqual(called, true)
1604
+ })
1605
+ })
1606
+ })
1607
+
1608
+ function getTestStream (encoding) {
1609
+ const word = 'hi'
1610
+ let i = 0
1611
+
1612
+ const stream = new Readable({
1613
+ read () {
1614
+ this.push(word[i] ? word[i++] : null)
1615
+ }
1616
+ })
1617
+
1618
+ if (encoding) {
1619
+ stream.setEncoding(encoding)
1620
+ }
1621
+
1622
+ return stream
1623
+ }
1624
+
1625
+ function readStream (stream, callback) {
1626
+ const chunks = []
1627
+
1628
+ stream.on('data', (chunk) => chunks.push(chunk))
1629
+
1630
+ stream.on('end', () => {
1631
+ return callback(Buffer.concat(chunks))
1632
+ })
1633
+ }
1634
+
1635
+ test('send cookie', (t, done) => {
1636
+ t.plan(3)
1637
+ const dispatch = function (req, res) {
1638
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1639
+ res.end(req.headers.host + '|' + req.headers.cookie)
1640
+ }
1641
+
1642
+ inject(dispatch, { url: 'http://example.com:8080/hello', cookies: { foo: 'bar', grass: 'àìùòlé' } }, (err, res) => {
1643
+ t.assert.ifError(err)
1644
+ t.assert.strictEqual(res.payload, 'example.com:8080|foo=bar; grass=%C3%A0%C3%AC%C3%B9%C3%B2l%C3%A9')
1645
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|foo=bar; grass=%C3%A0%C3%AC%C3%B9%C3%B2l%C3%A9')
1646
+ done()
1647
+ })
1648
+ })
1649
+
1650
+ test('send cookie with header already set', (t, done) => {
1651
+ t.plan(3)
1652
+ const dispatch = function (req, res) {
1653
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1654
+ res.end(req.headers.host + '|' + req.headers.cookie)
1655
+ }
1656
+
1657
+ inject(dispatch, {
1658
+ url: 'http://example.com:8080/hello',
1659
+ headers: { cookie: 'custom=one' },
1660
+ cookies: { foo: 'bar', grass: 'àìùòlé' }
1661
+ }, (err, res) => {
1662
+ t.assert.ifError(err)
1663
+ t.assert.strictEqual(res.payload, 'example.com:8080|custom=one; foo=bar; grass=%C3%A0%C3%AC%C3%B9%C3%B2l%C3%A9')
1664
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|custom=one; foo=bar; grass=%C3%A0%C3%AC%C3%B9%C3%B2l%C3%A9')
1665
+ done()
1666
+ })
1667
+ })
1668
+
1669
+ test('read cookie', (t, done) => {
1670
+ t.plan(3)
1671
+ const dispatch = function (req, res) {
1672
+ res.setHeader('Set-Cookie', [
1673
+ 'type=ninja',
1674
+ 'dev=me; Expires=Fri, 17 Jan 2020 20:26:08 -0000; Max-Age=1234; Domain=.home.com; Path=/wow; Secure; HttpOnly; SameSite=Strict'
1675
+ ])
1676
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
1677
+ res.end(req.headers.host + '|' + req.headers.cookie)
1678
+ }
1679
+
1680
+ inject(dispatch, { url: 'http://example.com:8080/hello', cookies: { foo: 'bar' } }, (err, res) => {
1681
+ t.assert.ifError(err)
1682
+ t.assert.strictEqual(res.payload, 'example.com:8080|foo=bar')
1683
+ t.assert.deepStrictEqual(res.cookies, [
1684
+ { name: 'type', value: 'ninja' },
1685
+ {
1686
+ name: 'dev',
1687
+ value: 'me',
1688
+ expires: new Date('Fri, 17 Jan 2020 20:26:08 -0000'),
1689
+ maxAge: 1234,
1690
+ domain: '.home.com',
1691
+ path: '/wow',
1692
+ secure: true,
1693
+ httpOnly: true,
1694
+ sameSite: 'Strict'
1695
+ }
1696
+ ])
1697
+ done()
1698
+ })
1699
+ })
1700
+
1701
+ test('correctly handles no string headers', (t, done) => {
1702
+ t.plan(3)
1703
+ const dispatch = function (req, res) {
1704
+ const payload = JSON.stringify(req.headers)
1705
+ res.writeHead(200, {
1706
+ 'Content-Type': 'application/json',
1707
+ integer: 12,
1708
+ float: 3.14,
1709
+ null: null,
1710
+ string: 'string',
1711
+ object: { foo: 'bar' },
1712
+ array: [1, 'two', 3],
1713
+ date,
1714
+ true: true,
1715
+ false: false
1716
+ })
1717
+ res.end(payload)
1718
+ }
1719
+
1720
+ const date = new Date(0)
1721
+ const headers = {
1722
+ integer: 12,
1723
+ float: 3.14,
1724
+ null: null,
1725
+ string: 'string',
1726
+ object: { foo: 'bar' },
1727
+ array: [1, 'two', 3],
1728
+ date,
1729
+ true: true,
1730
+ false: false
1731
+ }
1732
+
1733
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080/hello', headers }, (err, res) => {
1734
+ t.assert.ifError(err)
1735
+
1736
+ t.assert.deepStrictEqual(res.headers, {
1737
+ integer: '12',
1738
+ float: '3.14',
1739
+ null: 'null',
1740
+ string: 'string',
1741
+ object: '[object Object]',
1742
+ array: ['1', 'two', '3'],
1743
+ date: date.toString(),
1744
+ true: 'true',
1745
+ false: 'false',
1746
+ connection: 'keep-alive',
1747
+ 'transfer-encoding': 'chunked',
1748
+ 'content-type': 'application/json'
1749
+ })
1750
+
1751
+ t.assert.deepStrictEqual(JSON.parse(res.payload), {
1752
+ integer: '12',
1753
+ float: '3.14',
1754
+ null: 'null',
1755
+ string: 'string',
1756
+ object: '[object Object]',
1757
+ array: '1,two,3',
1758
+ date: date.toString(),
1759
+ true: 'true',
1760
+ false: 'false',
1761
+ host: 'example.com:8080',
1762
+ 'user-agent': 'lightMyRequest'
1763
+ })
1764
+ done()
1765
+ })
1766
+ })
1767
+
1768
+ test('errors for invalid undefined header value', (t, done) => {
1769
+ t.plan(1)
1770
+ try {
1771
+ inject(() => {}, { url: '/', headers: { 'header-key': undefined } }, () => {})
1772
+ } catch (err) {
1773
+ t.assert.ok(err)
1774
+ done()
1775
+ }
1776
+ })
1777
+
1778
+ test('example with form-auto-content', (t, done) => {
1779
+ t.plan(4)
1780
+ const dispatch = function (req, res) {
1781
+ let body = ''
1782
+ req.on('data', d => {
1783
+ body += d
1784
+ })
1785
+ req.on('end', () => {
1786
+ res.end(body)
1787
+ })
1788
+ }
1789
+
1790
+ const form = formAutoContent({
1791
+ myField: 'my value',
1792
+ myFile: fs.createReadStream('./LICENSE')
1793
+ })
1794
+
1795
+ inject(dispatch, {
1796
+ method: 'POST',
1797
+ url: 'http://example.com:8080/hello',
1798
+ payload: form.payload,
1799
+ headers: form.headers
1800
+ }, (err, res) => {
1801
+ t.assert.ifError(err)
1802
+ t.assert.strictEqual(res.statusCode, 200)
1803
+ t.assert.ok(/--.+\r\nContent-Disposition: form-data; name="myField"\r\n\r\nmy value\r\n--.*/.test(res.payload))
1804
+ t.assert.ok(/--.+\r\nContent-Disposition: form-data; name="myFile"; filename="LICENSE"\r\n.*/.test(res.payload))
1805
+ done()
1806
+ })
1807
+ })
1808
+
1809
+ test('simulate invalid alter _lightMyRequest.isDone with end', (t, done) => {
1810
+ const dispatch = function (req) {
1811
+ req.resume()
1812
+ req._lightMyRequest.isDone = true
1813
+ req.on('end', () => {
1814
+ t.assert.ok('should have end event')
1815
+ done()
1816
+ })
1817
+ }
1818
+
1819
+ inject(dispatch, { method: 'GET', url: '/', simulate: { end: true } }, () => {
1820
+ t.assert.fail('should not have reply')
1821
+ })
1822
+ })
1823
+
1824
+ test('simulate invalid alter _lightMyRequest.isDone without end', (t, done) => {
1825
+ const dispatch = function (req) {
1826
+ req.resume()
1827
+ req._lightMyRequest.isDone = true
1828
+ req.on('end', () => {
1829
+ t.assert.fail('should not have end event')
1830
+ })
1831
+ done()
1832
+ }
1833
+
1834
+ inject(dispatch, { method: 'GET', url: '/', simulate: { end: false } }, () => {
1835
+ t.assert.fail('should not have reply')
1836
+ })
1837
+ })
1838
+
1839
+ test('no error for response destroy', (t, done) => {
1840
+ t.plan(2)
1841
+
1842
+ const dispatch = function (_req, res) {
1843
+ res.destroy()
1844
+ }
1845
+
1846
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1847
+ t.assert.equal(res, null)
1848
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
1849
+ done()
1850
+ })
1851
+ })
1852
+
1853
+ test('request destory without.assert.ifError', (t, done) => {
1854
+ t.plan(2)
1855
+
1856
+ const dispatch = function (req) {
1857
+ req.destroy()
1858
+ }
1859
+
1860
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1861
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
1862
+ t.assert.equal(res, null)
1863
+ done()
1864
+ })
1865
+ })
1866
+
1867
+ test('request destory with error', (t, done) => {
1868
+ t.plan(2)
1869
+
1870
+ const fakeError = new Error('some-err')
1871
+
1872
+ const dispatch = function (req) {
1873
+ req.destroy(fakeError)
1874
+ }
1875
+
1876
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1877
+ t.assert.strictEqual(err, fakeError)
1878
+ t.assert.strictEqual(res, null)
1879
+ done()
1880
+ })
1881
+ })
1882
+
1883
+ test('compatible with stream.finished', (t, done) => {
1884
+ t.plan(3)
1885
+
1886
+ const dispatch = function (req, res) {
1887
+ finished(res, (err) => {
1888
+ t.assert.ok(err instanceof Error)
1889
+ })
1890
+
1891
+ req.destroy()
1892
+ }
1893
+
1894
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1895
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
1896
+ t.assert.equal(res, null)
1897
+ done()
1898
+ })
1899
+ })
1900
+
1901
+ test('compatible with eos', (t, done) => {
1902
+ t.plan(4)
1903
+
1904
+ const dispatch = function (req, res) {
1905
+ eos(res, (err) => {
1906
+ t.assert.ok(err instanceof Error)
1907
+ })
1908
+
1909
+ req.destroy()
1910
+ }
1911
+
1912
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1913
+ t.assert.ok(err)
1914
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
1915
+ t.assert.equal(res, null)
1916
+ done()
1917
+ })
1918
+ })
1919
+
1920
+ test('compatible with stream.finished pipe a Stream', (t, done) => {
1921
+ t.plan(3)
1922
+
1923
+ const dispatch = function (_req, res) {
1924
+ finished(res, (err) => {
1925
+ t.assert.ifError(err)
1926
+ })
1927
+
1928
+ new Readable({
1929
+ read () {
1930
+ this.push('hello world')
1931
+ this.push(null)
1932
+ }
1933
+ }).pipe(res)
1934
+ }
1935
+
1936
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1937
+ t.assert.ifError(err)
1938
+ t.assert.strictEqual(res.body, 'hello world')
1939
+ done()
1940
+ })
1941
+ })
1942
+
1943
+ test('compatible with eos, passes error correctly', (t, done) => {
1944
+ t.plan(3)
1945
+
1946
+ const fakeError = new Error('some-error')
1947
+
1948
+ const dispatch = function (req, res) {
1949
+ eos(res, (err) => {
1950
+ t.assert.strictEqual(err, fakeError)
1951
+ })
1952
+
1953
+ req.destroy(fakeError)
1954
+ }
1955
+
1956
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1957
+ t.assert.strictEqual(err, fakeError)
1958
+ t.assert.strictEqual(res, null)
1959
+ done()
1960
+ })
1961
+ })
1962
+
1963
+ test('multiple calls to req.destroy should not be called', (t, done) => {
1964
+ t.plan(2)
1965
+
1966
+ const dispatch = function (req) {
1967
+ req.destroy()
1968
+ req.destroy() // twice
1969
+ }
1970
+
1971
+ inject(dispatch, { method: 'GET', url: '/' }, (err, res) => {
1972
+ t.assert.equal(res, null)
1973
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
1974
+ done()
1975
+ })
1976
+ })
1977
+
1978
+ test('passes headers when using an express app', (t, done) => {
1979
+ t.plan(2)
1980
+
1981
+ const app = express()
1982
+
1983
+ app.get('/hello', (_req, res) => {
1984
+ res.setHeader('Some-Fancy-Header', 'a very cool value')
1985
+ res.end()
1986
+ })
1987
+
1988
+ inject(app, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
1989
+ t.assert.ifError(err)
1990
+ t.assert.strictEqual(res.headers['some-fancy-header'], 'a very cool value')
1991
+ done()
1992
+ })
1993
+ })
1994
+
1995
+ test('value of request url when using inject should not differ', (t, done) => {
1996
+ t.plan(1)
1997
+
1998
+ const server = http.createServer()
1999
+
2000
+ const dispatch = function (req, res) {
2001
+ res.end(req.url)
2002
+ }
2003
+
2004
+ inject(dispatch, { method: 'GET', url: 'http://example.com:8080//hello', server })
2005
+ .then(res => { t.assert.strictEqual(res.body, '//hello') })
2006
+ .catch(err => t.assert.ifError(err))
2007
+ .finally(done)
2008
+ })
2009
+
2010
+ test('Can parse paths with single leading slash', (t) => {
2011
+ t.plan(1)
2012
+ const parsedURL = parseURL('/test', undefined)
2013
+ t.assert.strictEqual(parsedURL.href, 'http://localhost/test')
2014
+ })
2015
+
2016
+ test('Can parse paths with two leading slashes', (t) => {
2017
+ t.plan(1)
2018
+ const parsedURL = parseURL('//test', undefined)
2019
+ t.assert.strictEqual(parsedURL.href, 'http://localhost//test')
2020
+ })
2021
+
2022
+ test('Can parse URLs with two leading slashes', (t) => {
2023
+ t.plan(1)
2024
+ const parsedURL = parseURL('https://example.com//test', undefined)
2025
+ t.assert.strictEqual(parsedURL.href, 'https://example.com//test')
2026
+ })
2027
+
2028
+ test('Can parse URLs with single leading slash', (t) => {
2029
+ t.plan(1)
2030
+ const parsedURL = parseURL('https://example.com/test', undefined)
2031
+ t.assert.strictEqual(parsedURL.href, 'https://example.com/test')
2032
+ })
2033
+
2034
+ test('Can abort a request using AbortController/AbortSignal', (t) => {
2035
+ t.plan(1)
2036
+
2037
+ const dispatch = function () {}
2038
+
2039
+ const controller = new AbortController()
2040
+ const promise = inject(dispatch, {
2041
+ method: 'GET',
2042
+ url: 'http://example.com:8080/hello',
2043
+ signal: controller.signal
2044
+ })
2045
+ controller.abort()
2046
+ const wanted = new Error('The operation was aborted')
2047
+ wanted.name = 'AbortError'
2048
+ t.assert.rejects(promise, wanted)
2049
+ }, { skip: globalThis.AbortController == null })
2050
+
2051
+ test('should pass req to ServerResponse', (t, done) => {
2052
+ if (parseInt(process.versions.node.split('.', 1)[0], 10) < 16) {
2053
+ t.assert.ok('Skip because Node version < 16')
2054
+ t.end()
2055
+ return
2056
+ }
2057
+
2058
+ t.plan(5)
2059
+ const dispatch = function (req, res) {
2060
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
2061
+ res.end(req.headers.host + '|' + req.url)
2062
+ }
2063
+
2064
+ inject(dispatch, 'http://example.com:8080/hello', (err, res) => {
2065
+ t.assert.ifError(err)
2066
+ t.assert.ok(res.raw.req === res.raw.res.req)
2067
+ t.assert.ok(res.raw.res.req.removeListener)
2068
+ t.assert.strictEqual(res.payload, 'example.com:8080|/hello')
2069
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|/hello')
2070
+ done()
2071
+ })
2072
+ })
2073
+
2074
+ test('should work with pipeline', (t, done) => {
2075
+ t.plan(3)
2076
+ const dispatch = function (req, res) {
2077
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
2078
+ pipeline(req.headers.host + '|' + req.url, res, () => res.end())
2079
+ }
2080
+
2081
+ inject(dispatch, 'http://example.com:8080/hello', (err, res) => {
2082
+ t.assert.ifError(err)
2083
+ t.assert.strictEqual(res.payload, 'example.com:8080|/hello')
2084
+ t.assert.strictEqual(res.rawPayload.toString(), 'example.com:8080|/hello')
2085
+ done()
2086
+ })
2087
+ })
2088
+
2089
+ test('should leave the headers user-agent and content-type undefined when the headers are explicitly set to undefined in the inject', (t, done) => {
2090
+ t.plan(5)
2091
+ const dispatch = function (req, res) {
2092
+ t.assert.ok(Array.isArray(req.rawHeaders))
2093
+ t.assert.strictEqual(req.headers['user-agent'], undefined)
2094
+ t.assert.strictEqual(req.headers['content-type'], undefined)
2095
+ t.assert.strictEqual(req.headers['x-foo'], 'bar')
2096
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
2097
+ res.end('Ok')
2098
+ }
2099
+
2100
+ inject(dispatch, {
2101
+ url: 'http://example.com:8080/hello',
2102
+ method: 'POST',
2103
+ headers: {
2104
+ 'x-foo': 'bar',
2105
+ 'user-agent': undefined,
2106
+ 'content-type': undefined
2107
+ },
2108
+ body: {}
2109
+ }, (err) => {
2110
+ t.assert.ifError(err)
2111
+ done()
2112
+ })
2113
+ })
2114
+
2115
+ test("passes payload when using express' send", (t, done) => {
2116
+ t.plan(3)
2117
+
2118
+ const app = express()
2119
+
2120
+ app.get('/hello', (_req, res) => {
2121
+ res.send('some text')
2122
+ })
2123
+
2124
+ inject(app, { method: 'GET', url: 'http://example.com:8080/hello' }, (err, res) => {
2125
+ t.assert.ifError(err)
2126
+ t.assert.strictEqual(res.headers['content-length'], '9')
2127
+ t.assert.strictEqual(res.payload, 'some text')
2128
+ done()
2129
+ })
2130
+ })
2131
+
2132
+ test('request that is destroyed errors', (t, done) => {
2133
+ t.plan(2)
2134
+ const dispatch = function (req, res) {
2135
+ readStream(req, () => {
2136
+ req.destroy() // this should be a no-op
2137
+ setImmediate(() => {
2138
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
2139
+ res.end('hi')
2140
+ })
2141
+ })
2142
+ }
2143
+
2144
+ const payload = getTestStream()
2145
+
2146
+ inject(dispatch, { method: 'POST', url: '/', payload }, (err, res) => {
2147
+ t.assert.equal(res, null)
2148
+ t.assert.equal(err.code, 'LIGHT_ECONNRESET')
2149
+ done()
2150
+ })
2151
+ })
2152
+
2153
+ function runFormDataUnitTest (name, { FormData, Blob }) {
2154
+ test(`${name} - form-data should be handled correctly`, (t, done) => {
2155
+ t.plan(23)
2156
+
2157
+ const dispatch = function (req, res) {
2158
+ let body = ''
2159
+ t.assert.ok(/multipart\/form-data; boundary=----formdata-[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}(--)?$/.test(req.headers['content-type']), 'proper Content-Type provided')
2160
+ req.on('data', d => {
2161
+ body += d
2162
+ })
2163
+ req.on('end', () => {
2164
+ res.end(body)
2165
+ })
2166
+ }
2167
+
2168
+ const form = new FormData()
2169
+ form.append('field', 'value')
2170
+ form.append('blob', new Blob(['value']), '')
2171
+ form.append('blob-with-type', new Blob(['value'], { type: 'text/plain' }), '')
2172
+ form.append('blob-with-name', new Blob(['value']), 'file.txt')
2173
+ form.append('number', 1)
2174
+
2175
+ inject(dispatch, {
2176
+ method: 'POST',
2177
+ url: 'http://example.com:8080/hello',
2178
+ payload: form
2179
+ }, (err, res) => {
2180
+ t.assert.ifError(err)
2181
+ t.assert.strictEqual(res.statusCode, 200)
2182
+
2183
+ const regexp = [
2184
+ // header
2185
+ /^------formdata-[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}(--)?$/,
2186
+ // content-disposition
2187
+ /^Content-Disposition: form-data; name="(.*)"(; filename="(.*)")?$/,
2188
+ // content-type
2189
+ /^Content-Type: (.*)$/
2190
+ ]
2191
+ const readable = Readable.from(res.body.split('\r\n'))
2192
+ let i = 1
2193
+ readable.on('data', function (chunk) {
2194
+ switch (i) {
2195
+ case 1:
2196
+ case 5:
2197
+ case 10:
2198
+ case 15:
2199
+ case 20: {
2200
+ // header
2201
+ t.assert.ok(regexp[0].test(chunk), 'correct header')
2202
+ break
2203
+ }
2204
+ case 2:
2205
+ case 6:
2206
+ case 11:
2207
+ case 16: {
2208
+ // content-disposition
2209
+ t.assert.ok(regexp[1].test(chunk), 'correct content-disposition')
2210
+ break
2211
+ }
2212
+ case 7:
2213
+ case 12:
2214
+ case 17: {
2215
+ // content-type
2216
+ t.assert.ok(regexp[2].test(chunk), 'correct content-type')
2217
+ break
2218
+ }
2219
+ case 3:
2220
+ case 8:
2221
+ case 13:
2222
+ case 18: {
2223
+ // empty
2224
+ t.assert.strictEqual(chunk, '', 'correct space')
2225
+ break
2226
+ }
2227
+ case 4:
2228
+ case 9:
2229
+ case 14:
2230
+ case 19: {
2231
+ // value
2232
+ t.assert.strictEqual(chunk, 'value', 'correct value')
2233
+ break
2234
+ }
2235
+ }
2236
+ i++
2237
+ })
2238
+ done()
2239
+ })
2240
+ }, { skip: FormData == null || Blob == null })
2241
+ }
2242
+
2243
+ // supports >= node@18
2244
+ runFormDataUnitTest('native', { FormData: globalThis.FormData, Blob: globalThis.Blob })
2245
+ // supports >= node@16
2246
+ runFormDataUnitTest('undici', { FormData: require('undici').FormData, Blob: require('node:buffer').Blob })
2247
+ // supports >= node@14
2248
+ runFormDataUnitTest('formdata-node', { FormData: require('formdata-node').FormData, Blob: require('formdata-node').Blob })
2249
+
2250
+ test('QUERY method works', (t, done) => {
2251
+ t.plan(3)
2252
+ const dispatch = function (req, res) {
2253
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
2254
+ req.pipe(res)
2255
+ }
2256
+
2257
+ inject(dispatch, { method: 'QUERY', url: '/test', payload: { a: 1 } }, (err, res) => {
2258
+ t.assert.ifError(err)
2259
+ t.assert.strictEqual(res.headers['content-type'], 'application/json')
2260
+ t.assert.strictEqual(res.payload, '{"a":1}')
2261
+ done()
2262
+ })
2263
+ })
2264
+
2265
+ test('query method works', (t, done) => {
2266
+ t.plan(3)
2267
+ const dispatch = function (req, res) {
2268
+ res.writeHead(200, { 'content-type': req.headers['content-type'] })
2269
+ req.pipe(res)
2270
+ }
2271
+
2272
+ inject(dispatch, { method: 'query', url: '/test', payload: { a: 1 } }, (err, res) => {
2273
+ t.assert.ifError(err)
2274
+ t.assert.strictEqual(res.headers['content-type'], 'application/json')
2275
+ t.assert.strictEqual(res.payload, '{"a":1}')
2276
+ done()
2277
+ })
2278
+ })
2279
+
2280
+ test('should return the file content', async (t) => {
2281
+ const multerMiddleware = multer({
2282
+ storage: multer.memoryStorage(),
2283
+ limits: {
2284
+ fileSize: 1024
2285
+ }
2286
+ })
2287
+
2288
+ const app = express()
2289
+
2290
+ app.use((req, res, next) => {
2291
+ if (req.headers['content-type'].indexOf('multipart/form-data') === 0) {
2292
+ req.multipart = true
2293
+ }
2294
+ next()
2295
+ })
2296
+
2297
+ app.post('/hello', multerMiddleware.single('textFile'), (req, res) => {
2298
+ res.send(req.file.buffer.toString('utf8'))
2299
+ })
2300
+ app.use((err, req, res, next) => {
2301
+ console.warn(err)
2302
+ res.status(500).send('Something was wrong')
2303
+ })
2304
+
2305
+ const formData = new FormData()
2306
+ formData.append('textFile', new Blob(['some data']), 'sample.txt')
2307
+
2308
+ const response = await inject(app, {
2309
+ method: 'POST',
2310
+ url: 'http://example.com:8080/hello',
2311
+ payload: formData
2312
+ })
2313
+
2314
+ t.assert.equal(response.statusCode, 200)
2315
+ t.assert.equal(response.payload, 'some data')
2316
+ })