@mbtest/mountebank 2.9.2-beta.9050

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/bin/mb +136 -0
  4. package/package.json +71 -0
  5. package/releases.json +52 -0
  6. package/src/cli/api.js +112 -0
  7. package/src/cli/cli.js +420 -0
  8. package/src/controllers/configController.js +64 -0
  9. package/src/controllers/feedController.js +115 -0
  10. package/src/controllers/homeController.js +58 -0
  11. package/src/controllers/imposterController.js +328 -0
  12. package/src/controllers/impostersController.js +215 -0
  13. package/src/controllers/logsController.js +52 -0
  14. package/src/models/behaviors.js +553 -0
  15. package/src/models/behaviorsValidator.js +186 -0
  16. package/src/models/compatibility.js +133 -0
  17. package/src/models/dryRunValidator.js +261 -0
  18. package/src/models/filesystemBackedImpostersRepository.js +908 -0
  19. package/src/models/http/baseHttpServer.js +207 -0
  20. package/src/models/http/headersMap.js +87 -0
  21. package/src/models/http/httpProxy.js +230 -0
  22. package/src/models/http/httpRequest.js +82 -0
  23. package/src/models/http/httpServer.js +18 -0
  24. package/src/models/http/index.js +18 -0
  25. package/src/models/https/cert/mb-cert.pem +20 -0
  26. package/src/models/https/cert/mb-csr.pem +16 -0
  27. package/src/models/https/cert/mb-key.pem +27 -0
  28. package/src/models/https/httpsServer.js +42 -0
  29. package/src/models/https/index.js +18 -0
  30. package/src/models/imposter.js +243 -0
  31. package/src/models/imposterPrinter.js +120 -0
  32. package/src/models/impostersRepository.js +49 -0
  33. package/src/models/inMemoryImpostersRepository.js +418 -0
  34. package/src/models/jsonpath.js +44 -0
  35. package/src/models/mbConnection.js +107 -0
  36. package/src/models/predicates.js +438 -0
  37. package/src/models/protocols.js +242 -0
  38. package/src/models/responseResolver.js +398 -0
  39. package/src/models/smtp/index.js +16 -0
  40. package/src/models/smtp/smtpRequest.js +60 -0
  41. package/src/models/smtp/smtpServer.js +109 -0
  42. package/src/models/tcp/index.js +18 -0
  43. package/src/models/tcp/tcpProxy.js +110 -0
  44. package/src/models/tcp/tcpRequest.js +23 -0
  45. package/src/models/tcp/tcpServer.js +156 -0
  46. package/src/models/tcp/tcpValidator.js +19 -0
  47. package/src/models/xpath.js +95 -0
  48. package/src/mountebank.js +245 -0
  49. package/src/public/images/arrow_down.png +0 -0
  50. package/src/public/images/arrow_up.png +0 -0
  51. package/src/public/images/book.jpg +0 -0
  52. package/src/public/images/dataflow.png +0 -0
  53. package/src/public/images/favicon.ico +0 -0
  54. package/src/public/images/forkme_right_orange_ff7600.png +0 -0
  55. package/src/public/images/mountebank.png +0 -0
  56. package/src/public/images/overview.gif +0 -0
  57. package/src/public/images/quote.png +0 -0
  58. package/src/public/images/tw-logo.png +0 -0
  59. package/src/public/scripts/jquery/jquery-3.6.1.min.js +2 -0
  60. package/src/public/scripts/urlHashHandler.js +31 -0
  61. package/src/public/stylesheets/application.css +424 -0
  62. package/src/public/stylesheets/ie.css +14 -0
  63. package/src/public/stylesheets/imposters.css +121 -0
  64. package/src/public/stylesheets/jqueryui/1.10.4/themes/smoothness/jquery-ui.css +1178 -0
  65. package/src/util/combinators.js +68 -0
  66. package/src/util/date.js +51 -0
  67. package/src/util/errors.js +55 -0
  68. package/src/util/helpers.js +131 -0
  69. package/src/util/inherit.js +28 -0
  70. package/src/util/ip.js +54 -0
  71. package/src/util/logger.js +83 -0
  72. package/src/util/middleware.js +256 -0
  73. package/src/util/scopedLogger.js +47 -0
  74. package/src/views/_footer.ejs +20 -0
  75. package/src/views/_header.ejs +113 -0
  76. package/src/views/_imposter.ejs +8 -0
  77. package/src/views/config.ejs +71 -0
  78. package/src/views/docs/api/behaviors/copy.ejs +427 -0
  79. package/src/views/docs/api/behaviors/decorate.ejs +182 -0
  80. package/src/views/docs/api/behaviors/lookup.ejs +220 -0
  81. package/src/views/docs/api/behaviors/shellTransform.ejs +153 -0
  82. package/src/views/docs/api/behaviors/wait.ejs +121 -0
  83. package/src/views/docs/api/behaviors.ejs +141 -0
  84. package/src/views/docs/api/contracts/addStub-description.ejs +10 -0
  85. package/src/views/docs/api/contracts/addStub.ejs +10 -0
  86. package/src/views/docs/api/contracts/config-description.ejs +32 -0
  87. package/src/views/docs/api/contracts/config.ejs +23 -0
  88. package/src/views/docs/api/contracts/home-description.ejs +18 -0
  89. package/src/views/docs/api/contracts/home.ejs +13 -0
  90. package/src/views/docs/api/contracts/imposter-description.ejs +439 -0
  91. package/src/views/docs/api/contracts/imposter.ejs +182 -0
  92. package/src/views/docs/api/contracts/imposters-description.ejs +13 -0
  93. package/src/views/docs/api/contracts/imposters.ejs +13 -0
  94. package/src/views/docs/api/contracts/logs-description.ejs +3 -0
  95. package/src/views/docs/api/contracts/logs.ejs +14 -0
  96. package/src/views/docs/api/contracts/stub-description.ejs +4 -0
  97. package/src/views/docs/api/contracts/stub.ejs +7 -0
  98. package/src/views/docs/api/contracts/stubs-description.ejs +4 -0
  99. package/src/views/docs/api/contracts/stubs.ejs +11 -0
  100. package/src/views/docs/api/contracts.ejs +133 -0
  101. package/src/views/docs/api/errors.ejs +64 -0
  102. package/src/views/docs/api/fault/connectionReset.ejs +31 -0
  103. package/src/views/docs/api/fault/randomDataThenClose.ejs +31 -0
  104. package/src/views/docs/api/faults.ejs +57 -0
  105. package/src/views/docs/api/injection.ejs +426 -0
  106. package/src/views/docs/api/json.ejs +205 -0
  107. package/src/views/docs/api/jsonpath.ejs +210 -0
  108. package/src/views/docs/api/mocks.ejs +130 -0
  109. package/src/views/docs/api/overview.ejs +968 -0
  110. package/src/views/docs/api/predicates/and.ejs +62 -0
  111. package/src/views/docs/api/predicates/contains.ejs +64 -0
  112. package/src/views/docs/api/predicates/deepEquals.ejs +114 -0
  113. package/src/views/docs/api/predicates/endsWith.ejs +66 -0
  114. package/src/views/docs/api/predicates/equals.ejs +125 -0
  115. package/src/views/docs/api/predicates/exists.ejs +118 -0
  116. package/src/views/docs/api/predicates/inject.ejs +67 -0
  117. package/src/views/docs/api/predicates/matches.ejs +66 -0
  118. package/src/views/docs/api/predicates/not.ejs +52 -0
  119. package/src/views/docs/api/predicates/or.ejs +79 -0
  120. package/src/views/docs/api/predicates/startsWith.ejs +62 -0
  121. package/src/views/docs/api/predicates.ejs +382 -0
  122. package/src/views/docs/api/proxies.ejs +191 -0
  123. package/src/views/docs/api/proxy/addDecorateBehavior.ejs +115 -0
  124. package/src/views/docs/api/proxy/addWaitBehavior.ejs +96 -0
  125. package/src/views/docs/api/proxy/injectHeaders.ejs +91 -0
  126. package/src/views/docs/api/proxy/predicateGenerators.ejs +600 -0
  127. package/src/views/docs/api/proxy/proxyModes.ejs +495 -0
  128. package/src/views/docs/api/stubs.ejs +391 -0
  129. package/src/views/docs/api/xpath.ejs +281 -0
  130. package/src/views/docs/cli/configFiles.ejs +133 -0
  131. package/src/views/docs/cli/customFormatters.ejs +53 -0
  132. package/src/views/docs/cli/help.ejs +6 -0
  133. package/src/views/docs/cli/replay.ejs +42 -0
  134. package/src/views/docs/cli/restart.ejs +10 -0
  135. package/src/views/docs/cli/save.ejs +68 -0
  136. package/src/views/docs/cli/start.ejs +234 -0
  137. package/src/views/docs/cli/stop.ejs +32 -0
  138. package/src/views/docs/commandLine.ejs +93 -0
  139. package/src/views/docs/communityExtensions.ejs +233 -0
  140. package/src/views/docs/gettingStarted.ejs +146 -0
  141. package/src/views/docs/mentalModel.ejs +51 -0
  142. package/src/views/docs/protocols/custom.ejs +231 -0
  143. package/src/views/docs/protocols/http.ejs +238 -0
  144. package/src/views/docs/protocols/https.ejs +246 -0
  145. package/src/views/docs/protocols/smtp.ejs +142 -0
  146. package/src/views/docs/protocols/tcp.ejs +431 -0
  147. package/src/views/docs/security.ejs +38 -0
  148. package/src/views/faqs.ejs +65 -0
  149. package/src/views/feed.ejs +33 -0
  150. package/src/views/imposter.ejs +22 -0
  151. package/src/views/imposters.ejs +33 -0
  152. package/src/views/index.ejs +89 -0
  153. package/src/views/license.ejs +30 -0
  154. package/src/views/logs.ejs +77 -0
  155. package/src/views/releases/v1.1.0.ejs +55 -0
  156. package/src/views/releases/v1.1.36.ejs +84 -0
  157. package/src/views/releases/v1.1.72.ejs +92 -0
  158. package/src/views/releases/v1.10.0.ejs +108 -0
  159. package/src/views/releases/v1.11.0.ejs +109 -0
  160. package/src/views/releases/v1.12.0.ejs +96 -0
  161. package/src/views/releases/v1.13.0.ejs +118 -0
  162. package/src/views/releases/v1.14.0.ejs +107 -0
  163. package/src/views/releases/v1.14.1.ejs +94 -0
  164. package/src/views/releases/v1.15.0.ejs +113 -0
  165. package/src/views/releases/v1.16.0.ejs +104 -0
  166. package/src/views/releases/v1.2.0.ejs +78 -0
  167. package/src/views/releases/v1.2.103.ejs +86 -0
  168. package/src/views/releases/v1.2.122.ejs +86 -0
  169. package/src/views/releases/v1.2.30.ejs +84 -0
  170. package/src/views/releases/v1.2.45.ejs +84 -0
  171. package/src/views/releases/v1.2.56.ejs +79 -0
  172. package/src/views/releases/v1.3.0.ejs +86 -0
  173. package/src/views/releases/v1.3.1.ejs +100 -0
  174. package/src/views/releases/v1.4.0.ejs +96 -0
  175. package/src/views/releases/v1.4.1.ejs +103 -0
  176. package/src/views/releases/v1.4.2.ejs +100 -0
  177. package/src/views/releases/v1.4.3.ejs +113 -0
  178. package/src/views/releases/v1.5.0.ejs +104 -0
  179. package/src/views/releases/v1.5.1.ejs +91 -0
  180. package/src/views/releases/v1.6.0.ejs +109 -0
  181. package/src/views/releases/v1.7.0.ejs +113 -0
  182. package/src/views/releases/v1.7.1.ejs +90 -0
  183. package/src/views/releases/v1.7.2.ejs +96 -0
  184. package/src/views/releases/v1.8.0.ejs +121 -0
  185. package/src/views/releases/v1.9.0.ejs +111 -0
  186. package/src/views/releases/v2.0.0.ejs +159 -0
  187. package/src/views/releases/v2.1.0.ejs +121 -0
  188. package/src/views/releases/v2.1.1.ejs +106 -0
  189. package/src/views/releases/v2.1.2.ejs +84 -0
  190. package/src/views/releases/v2.2.0.ejs +115 -0
  191. package/src/views/releases/v2.2.1.ejs +102 -0
  192. package/src/views/releases/v2.3.0.ejs +121 -0
  193. package/src/views/releases/v2.3.1.ejs +100 -0
  194. package/src/views/releases/v2.3.2.ejs +102 -0
  195. package/src/views/releases/v2.3.3.ejs +97 -0
  196. package/src/views/releases/v2.4.0.ejs +114 -0
  197. package/src/views/releases/v2.5.0.ejs +51 -0
  198. package/src/views/releases/v2.6.0.ejs +35 -0
  199. package/src/views/releases/v2.7.0.ejs +32 -0
  200. package/src/views/releases/v2.8.0.ejs +36 -0
  201. package/src/views/releases/v2.8.1.ejs +7 -0
  202. package/src/views/releases/v2.8.2.ejs +26 -0
  203. package/src/views/releases/v2.9.0.ejs +32 -0
  204. package/src/views/releases/v2.9.1.ejs +10 -0
  205. package/src/views/releases.ejs +26 -0
  206. package/src/views/sitemap.ejs +36 -0
  207. package/src/views/support.ejs +14 -0
@@ -0,0 +1,231 @@
1
+ <%
2
+ title = 'custom protocols'
3
+ description = 'How to create your own protocol implementation'
4
+ %>
5
+
6
+ <%- include('../../_header') -%>
7
+
8
+ <h1>how to create your own protocol implementation</h1>
9
+
10
+ <p>As of mountebank 2.0.0, you can create your own protocol implementation in the language of your choice.
11
+ You do not have to change the mountebank source code to do so. You can see a fully worked example
12
+ at <a href='https://github.com/mountebank-testing/mountebank-http'>mountebank-http</a>.</p>
13
+
14
+ <p>In mountebank land, a <em>protocol</em> has the following responsibilities:</p>
15
+
16
+ <ul class='bullet-list'>
17
+ <li>Listen for incoming requests</li>
18
+ <li>Translate a network request into a JSON representation</li>
19
+ <li>Pass the JSON request to mountebank, which returns a JSON response representation</li>
20
+ <li>If necessary, proxy to a downstream server</li>
21
+ <li>Translate the JSON response into a network response</li>
22
+ </ul>
23
+
24
+ <p>The sequence diagram below -- thanks to Max Ludwig -- shows the general idea (without proxying):</p>
25
+ <img src='/images/dataflow.png' alt='Building custom protocols' />
26
+
27
+ <h2>Command line interface</h2>
28
+
29
+ <p>To inform mountebank of your custom protocol, you create a protocols configuration file. By default,
30
+ this will be called "protocols.json" and is expected to reside in the working directory you start
31
+ <code>mb</code> in. You can change it with the <code>--protofile</code> command line flag. The following
32
+ configuration would override mountebank's built-in <code>http</code> protocol with
33
+ a custom implementation and add a new protocol called "foo". Start by adding the following to "protocols.json":</p>
34
+
35
+ <pre><code>
36
+ {
37
+ "http": {
38
+ "createCommand": "node http.js",
39
+ "testRequest": {
40
+ "method": "GET",
41
+ "path": "/",
42
+ "query": {},
43
+ "headers": {},
44
+ "form": {},
45
+ "body": ""
46
+ },
47
+ "testProxyResponse": {
48
+ "statusCode": 200,
49
+ "headers": {},
50
+ "body": ""
51
+ }
52
+ },
53
+ "foo": {
54
+ "createCommand": "java foo",
55
+ }
56
+ }</code></pre>
57
+
58
+ <p>You could run this with the following command:</p>
59
+
60
+ <pre><code>mb --protofile protocols.json</code></pre>
61
+
62
+ <p>The most important field is the <code>createCommand</code>, which tells mountebank the command line
63
+ information needed to start a new instance of the protocol. As far as mountebank is concerned, it's
64
+ just a shell command. That gives you enormous flexibility in how you implement it.</p>
65
+
66
+ <p>The other two fields are optional and used for validation. When a new imposter is created, mountebank performs
67
+ a dry run of the creation, testing all predicates and responses to make sure none of them return an error.
68
+ The <code>testRequest</code> and <code>testProxyResponse</code> fields should model the protocol-specific
69
+ request and response format, which will be used during the dry run. Adding them makes that validation
70
+ more robust.</p>
71
+
72
+ <p>When spinning up an imposter, mountebank will call the <code>createCommand</code>, passing a JSON
73
+ string as an additional parameter. When parsed into JSON, the object will contain the following fields:</p>
74
+
75
+ <table>
76
+ <tr>
77
+ <th>Field</th>
78
+ <th>Description</th>
79
+ </tr>
80
+ <tr>
81
+ <td><code>port</code></td>
82
+ <td>The port to listen to. While you are always free to require it, the built-in mountebank protocols
83
+ make this an optional field. If it's missing, you are free to pick any open port.</td>
84
+ </tr>
85
+ <tr>
86
+ <td><code>host</code></td>
87
+ <td>If passed, bind to the provided host name</td>
88
+ </tr>
89
+ <tr>
90
+ <td><code>callbackURLTemplate</code></td>
91
+ <td>A URL template that will look something like "http://localhost:2525/imposters/:port/_requests".
92
+ Replace <code>:port</code> with the actual server port, and use that URL to communicate with mountebank.
93
+ Every time you get a new request, after converting it to JSON, you'll <code>POST</code> that JSON
94
+ to the given URL, and mountebank will give you the JSON response.</td>
95
+ </tr>
96
+ <tr>
97
+ <td><code>loglevel</code></td>
98
+ <td>The logging level. Everything you write to standard out (stdout) that starts with one of the standard
99
+ log levels (debug, info, warn, error) will be written to the mountebank log. You may decide to use
100
+ this parameter to optimize what you write to stdout.</td>
101
+ </tr>
102
+ <tr>
103
+ <td><code>allowInjection</code></td>
104
+ <td>The value of the <code>--allowInjection</code> command line flag. Use this if you have some custom
105
+ injection code mountebank is unaware of.</td>
106
+ </tr>
107
+ <tr>
108
+ <td><code>defaultResponse</code></td>
109
+ <td>The default response JSON object, to be used to fill in missing response fields in the responses
110
+ provided by the user.</td>
111
+ </tr>
112
+ <tr>
113
+ <td><em>Custom protocol fields</em></td>
114
+ <td>Mountebank will pass any fields it does not recognize. This allows you to have custom metadata
115
+ (like the <code>mode</code> field in the <code>tcp</code> protocol).</td>
116
+ </tr>
117
+ </table>
118
+
119
+ <p>After you parse the JSON object, you spin up your server, listening on the provided socket.
120
+ As soon as you write anything to stdout, mountebank assumes you have finished initializing.</p>
121
+
122
+ <h2>The API</h2>
123
+
124
+ <p>When a network request comes in, you translate it to a simplified JSON format and wrap that
125
+ inside an object with a top-level <code>"request"</code> key. For example, the following could
126
+ represent a messaging protocol with custom request fields for the <code>message</code> and <code>transactionId</code>:</p>
127
+
128
+ <pre><code>{
129
+ "request": {
130
+ "message": "Hello, world!",
131
+ "transactionId": 123
132
+ }
133
+ }</code></pre>
134
+
135
+ <p>The next step is to <code>POST</code> that body to the <code>callbackURLTemplate</code>
136
+ (with ":port" replaced with the actual server port if you changed it). Mountebank will respond with
137
+ one of the three following responses:</p>
138
+
139
+ <h3>Standard response</h3>
140
+
141
+ <p>Mountebank was able to determine the
142
+ correct JSON response to use. The <code>POST</code> response looks something like this:</p>
143
+
144
+ <pre><code>{
145
+ "response": {
146
+ "statusCode": 400,
147
+ "body": "Error!!"
148
+ }
149
+ }</code></pre>
150
+
151
+ <p>All you have to do is to merge in the missing fields from the <code>defaultResponse</code>,
152
+ and translate the JSON to a network response.</p>
153
+
154
+ <h3>Proxy response</h3>
155
+
156
+ <p>If mountebank determines you need to proxy to fulfill the response, it will send a payload
157
+ that looks something like this:</p>
158
+
159
+ <pre><code>{
160
+ "proxy": {
161
+ "to": "http://origin-server"
162
+ },
163
+ "request": {
164
+ "method": "GET",
165
+ "path": "/",
166
+ "query": {},
167
+ "headers": {}
168
+ },
169
+ "callbackURL": "http://localhost:2525/imposters/3000/_requests/0
170
+ }</code></pre>
171
+
172
+ <p>Your job at this point is to forward the request on to the given proxy configuration. This requires
173
+ you to translate the JSON request into a network request to the proxy, and translate the captured
174
+ network response into a JSON object. Then you <code>POST</code> the JSON response to the provided
175
+ <code>callbackURL</code>. Mountebank will return you a standard <code>response</code> as shown above.
176
+ Mountebank will be responsible for saving the proxy responses; you do not need to worry about it.</p>
177
+
178
+ <h3>Blocked IPs</h3>
179
+
180
+ <p>If you are running mountebank with either the <code>--localOnly</code> or <code>--ipWhitelist</code>
181
+ command line flags, it's possible that the originating IP address of the request should be blocked.
182
+ You must add a field to the JSON request called "ip" with the originating address, and if it should
183
+ be blocked, mountebank will return something like the following payload:</p>
184
+
185
+ <pre><code>{
186
+ "blocked": true,
187
+ "code": "unauthorized ip address"
188
+ }</code></pre>
189
+
190
+ <p>In such scenarios, it is recommended that you kill the connection rather than return an error.
191
+ Mountebank will not return you a response.</p>
192
+
193
+ <h2>Logging</h2>
194
+
195
+ <p>Every message you write to stdout that begins with one of {debug, info, warn, error} will be written
196
+ to the mountebank log. While not strictly necessary, you can optimize the writes with the
197
+ <code>loglevel</code> parameter. The following creates a <code>log</code> function in JavaScript:</p>
198
+
199
+ <pre><code>
200
+ function createLogger (loglevel) {
201
+ const result = {},
202
+ levels = ['debug', 'info', 'warn', 'error'];
203
+
204
+ levels.forEach((level, index) => {
205
+ if (index &lt; levels.indexOf(loglevel)) {
206
+ result[level] = () => {};
207
+ }
208
+ else {
209
+ result[level] = function () {
210
+ const args = Array.prototype.slice.call(arguments),
211
+ message = require('util').format.apply(this, args);
212
+
213
+ console.log(`${level} ${message}`);
214
+ };
215
+ }
216
+ });
217
+ return result;
218
+ }
219
+
220
+ const config = JSON.parse(process.argv[2])
221
+ logger = createLogger(config.loglevle);
222
+
223
+ // Use as log.info('This is an info message');
224
+ </code></pre>
225
+
226
+ <h2>Error handling</h2>
227
+
228
+ <p>If you exit before writing to stdout, exit with a non-zero exit code. The user will get a 400
229
+ error.</p>
230
+
231
+ <%- include('../../_footer') -%>
@@ -0,0 +1,238 @@
1
+ <%
2
+ title = 'http'
3
+ description = 'The HTTP protocol support by mountebank'
4
+ %>
5
+
6
+ <%- include('../../_header') -%>
7
+
8
+ <h1>http</h1>
9
+
10
+ <h2>Imposter Creation Parameters</h2>
11
+
12
+ <table>
13
+ <tr>
14
+ <th>Parameter</th>
15
+ <th>Options</th>
16
+ <th>Required?</th>
17
+ <th>Default</th>
18
+ <th>Description</th>
19
+ </tr>
20
+ <tr>
21
+ <td><code>protocol</code></td>
22
+ <td><code>http</code></td>
23
+ <td>Yes</td>
24
+ <td>N/A</td>
25
+ <td>&nbsp;</td>
26
+ </tr>
27
+ <tr>
28
+ <td><code>port</code></td>
29
+ <td>Any valid port number</td>
30
+ <td>No</td>
31
+ <td>A randomly assigned port. mountebank will return the actual value
32
+ in the <code>POST</code> response.</td>
33
+ <td>The port to run the imposter on.</td>
34
+ </tr>
35
+ <tr>
36
+ <td><code>name</code></td>
37
+ <td>Any string</td>
38
+ <td>No</td>
39
+ <td>empty string</td>
40
+ <td>Included in the logs, useful when multiple imposters are set up.</td>
41
+ </tr>
42
+ <tr>
43
+ <td><code>recordRequests</code></td>
44
+ <td><code>true</code> or <code>false</code></td>
45
+ <td>No</td>
46
+ <td>false</td>
47
+ <td>Adds <a href='/docs/api/mocks'>mock verification</a> support by remembering the requests
48
+ made to this imposter. Note that this represents a memory leak for any long running
49
+ <code>mb</code> process, as requests are never forgotten.</td>
50
+ </tr>
51
+ <tr>
52
+ <td><code>stubs</code></td>
53
+ <td>Valid stubs</td>
54
+ <td>No</td>
55
+ <td>An empty array</td>
56
+ <td>The list of stubs responsible for matching a request and returning a response</td>
57
+ </tr>
58
+ <tr>
59
+ <td><code>defaultResponse</code></td>
60
+ <td>A valid response, see below for response fields</td>
61
+ <td>No</td>
62
+ <td><pre><code>
63
+ {
64
+ "statusCode": 200,
65
+ "headers": {
66
+ "connection": "close"
67
+ },
68
+ "body": ""
69
+ }
70
+ </code></pre></td>
71
+ <td>The default response to send if no predicate matches. Also represents the default values
72
+ that get merged into a response that doesn't specify every field</td>
73
+ </tr>
74
+ <tr>
75
+ <td><code>allowCORS</code></td>
76
+ <td>boolean</td>
77
+ <td>No</td>
78
+ <td>false</td>
79
+ <td>If true, mountebank will allow all CORS preflight requests on the imposter.</td>
80
+ </tr>
81
+ </table>
82
+
83
+ <p>http and https imposters prevent keepalive connections by default because they can lead
84
+ to some difficult to troubleshoot problems in use cases where you start in stop imposters
85
+ in the scope of one test. The test may shut down the imposter, which prevents new connections
86
+ for the port, but that won't prevent the system under test from trying to reuse an existing
87
+ keepalive socket. If you need to override that behavior, override the <code>defaultResponse</code>
88
+ field and explicitly set the <code>Connection</code> header to <code>keep-alive</code>.</p>
89
+
90
+ <h2>HTTP Requests</h2>
91
+
92
+ <table>
93
+ <tr>
94
+ <th>Field</th>
95
+ <th>Description</th>
96
+ <th>Type</th>
97
+ </tr>
98
+ <tr>
99
+ <td><code>requestFrom</code></td>
100
+ <td>The client socket, primarily used for logging and debugging.</td>
101
+ <td>string</td>
102
+ </tr>
103
+ <tr>
104
+ <td><code>path</code></td>
105
+ <td>The path of the request, without the querystring</td>
106
+ <td>string</td>
107
+ </tr>
108
+ <tr>
109
+ <td><code>query</code></td>
110
+ <td>The querystring of the request</td>
111
+ <td>object</td>
112
+ </tr>
113
+ <tr>
114
+ <td><code>method</code></td>
115
+ <td>The request method</td>
116
+ <td>string</td>
117
+ </tr>
118
+ <tr>
119
+ <td><code>headers</code></td>
120
+ <td>The HTTP headers</td>
121
+ <td>object</td>
122
+ </tr>
123
+ <tr>
124
+ <td><code>body</code></td>
125
+ <td>The request body</td>
126
+ <td>string</td>
127
+ </tr>
128
+ <tr>
129
+ <td><code>form</code></td>
130
+ <td>Form-encoded key-value pairs in the body. Supports key-specific predicates. For example,
131
+ with a body of <code>firstname=bob&lastname=smith</code>, you could set a predicate on
132
+ just <code>lastname</code>.</td>
133
+ <td>object</td>
134
+ </tr>
135
+ </table>
136
+
137
+ <h2>HTTP Responses</h2>
138
+
139
+ <table>
140
+ <tr>
141
+ <th>Field</th>
142
+ <th>Type</th>
143
+ <th>Default</th>
144
+ </tr>
145
+ <tr>
146
+ <td><code>statusCode</code></td>
147
+ <td>int</td>
148
+ <td><code>200</code></td>
149
+ </tr>
150
+ <tr>
151
+ <td><code>headers</code></td>
152
+ <td>object</td>
153
+ <td><code>{ "Connection": "close" }</code></td>
154
+ </tr>
155
+ <tr>
156
+ <td><code>body</code></td>
157
+ <td>string or object</td>
158
+ <td><code>""</code></td>
159
+ </tr>
160
+ <tr>
161
+ <td><code>_mode</code></td>
162
+ <td>string - <code>binary</code> or <code>text</code></td>
163
+ <td><code>text</code></td>
164
+ </tr>
165
+ </table>
166
+
167
+ <p>While HTTP bodies are strings, you can pass a JSON body in the API. That will be
168
+ turned into a valid JSON string when the response is sent.</p>
169
+
170
+ <p>HTTP bodies will always be recorded as text, but mountebank does have the ability
171
+ to respond in binary. If you want to set up a canned binary response, set the <code>_mode</code>
172
+ to <code>binary</code> and base64 encode the <code>body</code>. mountebank will also try
173
+ to preserve binary responses in proxies by looking at the <code>Content-Encoding</code> and
174
+ <code>Content-Type</code> headers.</p>
175
+
176
+ <h2 id='inline-json-response-bodies'>Inline JSON For Response Bodies</h2>
177
+
178
+ <p>The example below shows passing an inline JSON object as the response body.</p>
179
+
180
+ <testScenario name='json-example'>
181
+ <step type='http'>
182
+ <pre><code>POST /imposters HTTP/1.1
183
+ Host: localhost:<%= port %>
184
+ Accept: application/json
185
+ Content-Type: application/json
186
+
187
+ {
188
+ "port": 4545,
189
+ "protocol": "http",
190
+ "stubs": [
191
+ {
192
+ "responses": [
193
+ {
194
+ "is": {
195
+ "statusCode": 200,
196
+ "headers": {
197
+ "Content-Type": "application/json"
198
+ },
199
+ "body": {
200
+ "bikeId": 123,
201
+ "name": "Turbo Bike 4000"
202
+ }
203
+ }
204
+ }
205
+ ]
206
+ }
207
+ ]
208
+ }</code></pre>
209
+ </step>
210
+
211
+ <p>Now let's test the response by calling the imposter:</p>
212
+
213
+ <step type='http'>
214
+ <pre><code>GET / HTTP/1.1
215
+ Host: localhost:4545
216
+ Accept: application/json</code></pre>
217
+
218
+ <assertResponse>
219
+ <pre><code>HTTP/1.1 200 OK
220
+ Content-Type: application/json
221
+ Connection: close
222
+ Date: <volatile>Sun, 15 Nov 2015 01:02:03 GMT</volatile>
223
+ Transfer-Encoding: chunked
224
+
225
+ {
226
+ "bikeId": 123,
227
+ "name": "Turbo Bike 4000"
228
+ }</code></pre>
229
+ </assertResponse>
230
+ </step>
231
+
232
+ <step type='http'>
233
+ <code class='hidden'>DELETE /imposters/4545 HTTP/1.1
234
+ Host: localhost:<%= port %></code>
235
+ </step>
236
+ </testScenario>
237
+
238
+ <%- include('../../_footer') -%>