@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.
- package/LICENSE +21 -0
- package/README.md +94 -0
- package/bin/mb +136 -0
- package/package.json +71 -0
- package/releases.json +52 -0
- package/src/cli/api.js +112 -0
- package/src/cli/cli.js +420 -0
- package/src/controllers/configController.js +64 -0
- package/src/controllers/feedController.js +115 -0
- package/src/controllers/homeController.js +58 -0
- package/src/controllers/imposterController.js +328 -0
- package/src/controllers/impostersController.js +215 -0
- package/src/controllers/logsController.js +52 -0
- package/src/models/behaviors.js +553 -0
- package/src/models/behaviorsValidator.js +186 -0
- package/src/models/compatibility.js +133 -0
- package/src/models/dryRunValidator.js +261 -0
- package/src/models/filesystemBackedImpostersRepository.js +908 -0
- package/src/models/http/baseHttpServer.js +207 -0
- package/src/models/http/headersMap.js +87 -0
- package/src/models/http/httpProxy.js +230 -0
- package/src/models/http/httpRequest.js +82 -0
- package/src/models/http/httpServer.js +18 -0
- package/src/models/http/index.js +18 -0
- package/src/models/https/cert/mb-cert.pem +20 -0
- package/src/models/https/cert/mb-csr.pem +16 -0
- package/src/models/https/cert/mb-key.pem +27 -0
- package/src/models/https/httpsServer.js +42 -0
- package/src/models/https/index.js +18 -0
- package/src/models/imposter.js +243 -0
- package/src/models/imposterPrinter.js +120 -0
- package/src/models/impostersRepository.js +49 -0
- package/src/models/inMemoryImpostersRepository.js +418 -0
- package/src/models/jsonpath.js +44 -0
- package/src/models/mbConnection.js +107 -0
- package/src/models/predicates.js +438 -0
- package/src/models/protocols.js +242 -0
- package/src/models/responseResolver.js +398 -0
- package/src/models/smtp/index.js +16 -0
- package/src/models/smtp/smtpRequest.js +60 -0
- package/src/models/smtp/smtpServer.js +109 -0
- package/src/models/tcp/index.js +18 -0
- package/src/models/tcp/tcpProxy.js +110 -0
- package/src/models/tcp/tcpRequest.js +23 -0
- package/src/models/tcp/tcpServer.js +156 -0
- package/src/models/tcp/tcpValidator.js +19 -0
- package/src/models/xpath.js +95 -0
- package/src/mountebank.js +245 -0
- package/src/public/images/arrow_down.png +0 -0
- package/src/public/images/arrow_up.png +0 -0
- package/src/public/images/book.jpg +0 -0
- package/src/public/images/dataflow.png +0 -0
- package/src/public/images/favicon.ico +0 -0
- package/src/public/images/forkme_right_orange_ff7600.png +0 -0
- package/src/public/images/mountebank.png +0 -0
- package/src/public/images/overview.gif +0 -0
- package/src/public/images/quote.png +0 -0
- package/src/public/images/tw-logo.png +0 -0
- package/src/public/scripts/jquery/jquery-3.6.1.min.js +2 -0
- package/src/public/scripts/urlHashHandler.js +31 -0
- package/src/public/stylesheets/application.css +424 -0
- package/src/public/stylesheets/ie.css +14 -0
- package/src/public/stylesheets/imposters.css +121 -0
- package/src/public/stylesheets/jqueryui/1.10.4/themes/smoothness/jquery-ui.css +1178 -0
- package/src/util/combinators.js +68 -0
- package/src/util/date.js +51 -0
- package/src/util/errors.js +55 -0
- package/src/util/helpers.js +131 -0
- package/src/util/inherit.js +28 -0
- package/src/util/ip.js +54 -0
- package/src/util/logger.js +83 -0
- package/src/util/middleware.js +256 -0
- package/src/util/scopedLogger.js +47 -0
- package/src/views/_footer.ejs +20 -0
- package/src/views/_header.ejs +113 -0
- package/src/views/_imposter.ejs +8 -0
- package/src/views/config.ejs +71 -0
- package/src/views/docs/api/behaviors/copy.ejs +427 -0
- package/src/views/docs/api/behaviors/decorate.ejs +182 -0
- package/src/views/docs/api/behaviors/lookup.ejs +220 -0
- package/src/views/docs/api/behaviors/shellTransform.ejs +153 -0
- package/src/views/docs/api/behaviors/wait.ejs +121 -0
- package/src/views/docs/api/behaviors.ejs +141 -0
- package/src/views/docs/api/contracts/addStub-description.ejs +10 -0
- package/src/views/docs/api/contracts/addStub.ejs +10 -0
- package/src/views/docs/api/contracts/config-description.ejs +32 -0
- package/src/views/docs/api/contracts/config.ejs +23 -0
- package/src/views/docs/api/contracts/home-description.ejs +18 -0
- package/src/views/docs/api/contracts/home.ejs +13 -0
- package/src/views/docs/api/contracts/imposter-description.ejs +439 -0
- package/src/views/docs/api/contracts/imposter.ejs +182 -0
- package/src/views/docs/api/contracts/imposters-description.ejs +13 -0
- package/src/views/docs/api/contracts/imposters.ejs +13 -0
- package/src/views/docs/api/contracts/logs-description.ejs +3 -0
- package/src/views/docs/api/contracts/logs.ejs +14 -0
- package/src/views/docs/api/contracts/stub-description.ejs +4 -0
- package/src/views/docs/api/contracts/stub.ejs +7 -0
- package/src/views/docs/api/contracts/stubs-description.ejs +4 -0
- package/src/views/docs/api/contracts/stubs.ejs +11 -0
- package/src/views/docs/api/contracts.ejs +133 -0
- package/src/views/docs/api/errors.ejs +64 -0
- package/src/views/docs/api/fault/connectionReset.ejs +31 -0
- package/src/views/docs/api/fault/randomDataThenClose.ejs +31 -0
- package/src/views/docs/api/faults.ejs +57 -0
- package/src/views/docs/api/injection.ejs +426 -0
- package/src/views/docs/api/json.ejs +205 -0
- package/src/views/docs/api/jsonpath.ejs +210 -0
- package/src/views/docs/api/mocks.ejs +130 -0
- package/src/views/docs/api/overview.ejs +968 -0
- package/src/views/docs/api/predicates/and.ejs +62 -0
- package/src/views/docs/api/predicates/contains.ejs +64 -0
- package/src/views/docs/api/predicates/deepEquals.ejs +114 -0
- package/src/views/docs/api/predicates/endsWith.ejs +66 -0
- package/src/views/docs/api/predicates/equals.ejs +125 -0
- package/src/views/docs/api/predicates/exists.ejs +118 -0
- package/src/views/docs/api/predicates/inject.ejs +67 -0
- package/src/views/docs/api/predicates/matches.ejs +66 -0
- package/src/views/docs/api/predicates/not.ejs +52 -0
- package/src/views/docs/api/predicates/or.ejs +79 -0
- package/src/views/docs/api/predicates/startsWith.ejs +62 -0
- package/src/views/docs/api/predicates.ejs +382 -0
- package/src/views/docs/api/proxies.ejs +191 -0
- package/src/views/docs/api/proxy/addDecorateBehavior.ejs +115 -0
- package/src/views/docs/api/proxy/addWaitBehavior.ejs +96 -0
- package/src/views/docs/api/proxy/injectHeaders.ejs +91 -0
- package/src/views/docs/api/proxy/predicateGenerators.ejs +600 -0
- package/src/views/docs/api/proxy/proxyModes.ejs +495 -0
- package/src/views/docs/api/stubs.ejs +391 -0
- package/src/views/docs/api/xpath.ejs +281 -0
- package/src/views/docs/cli/configFiles.ejs +133 -0
- package/src/views/docs/cli/customFormatters.ejs +53 -0
- package/src/views/docs/cli/help.ejs +6 -0
- package/src/views/docs/cli/replay.ejs +42 -0
- package/src/views/docs/cli/restart.ejs +10 -0
- package/src/views/docs/cli/save.ejs +68 -0
- package/src/views/docs/cli/start.ejs +234 -0
- package/src/views/docs/cli/stop.ejs +32 -0
- package/src/views/docs/commandLine.ejs +93 -0
- package/src/views/docs/communityExtensions.ejs +233 -0
- package/src/views/docs/gettingStarted.ejs +146 -0
- package/src/views/docs/mentalModel.ejs +51 -0
- package/src/views/docs/protocols/custom.ejs +231 -0
- package/src/views/docs/protocols/http.ejs +238 -0
- package/src/views/docs/protocols/https.ejs +246 -0
- package/src/views/docs/protocols/smtp.ejs +142 -0
- package/src/views/docs/protocols/tcp.ejs +431 -0
- package/src/views/docs/security.ejs +38 -0
- package/src/views/faqs.ejs +65 -0
- package/src/views/feed.ejs +33 -0
- package/src/views/imposter.ejs +22 -0
- package/src/views/imposters.ejs +33 -0
- package/src/views/index.ejs +89 -0
- package/src/views/license.ejs +30 -0
- package/src/views/logs.ejs +77 -0
- package/src/views/releases/v1.1.0.ejs +55 -0
- package/src/views/releases/v1.1.36.ejs +84 -0
- package/src/views/releases/v1.1.72.ejs +92 -0
- package/src/views/releases/v1.10.0.ejs +108 -0
- package/src/views/releases/v1.11.0.ejs +109 -0
- package/src/views/releases/v1.12.0.ejs +96 -0
- package/src/views/releases/v1.13.0.ejs +118 -0
- package/src/views/releases/v1.14.0.ejs +107 -0
- package/src/views/releases/v1.14.1.ejs +94 -0
- package/src/views/releases/v1.15.0.ejs +113 -0
- package/src/views/releases/v1.16.0.ejs +104 -0
- package/src/views/releases/v1.2.0.ejs +78 -0
- package/src/views/releases/v1.2.103.ejs +86 -0
- package/src/views/releases/v1.2.122.ejs +86 -0
- package/src/views/releases/v1.2.30.ejs +84 -0
- package/src/views/releases/v1.2.45.ejs +84 -0
- package/src/views/releases/v1.2.56.ejs +79 -0
- package/src/views/releases/v1.3.0.ejs +86 -0
- package/src/views/releases/v1.3.1.ejs +100 -0
- package/src/views/releases/v1.4.0.ejs +96 -0
- package/src/views/releases/v1.4.1.ejs +103 -0
- package/src/views/releases/v1.4.2.ejs +100 -0
- package/src/views/releases/v1.4.3.ejs +113 -0
- package/src/views/releases/v1.5.0.ejs +104 -0
- package/src/views/releases/v1.5.1.ejs +91 -0
- package/src/views/releases/v1.6.0.ejs +109 -0
- package/src/views/releases/v1.7.0.ejs +113 -0
- package/src/views/releases/v1.7.1.ejs +90 -0
- package/src/views/releases/v1.7.2.ejs +96 -0
- package/src/views/releases/v1.8.0.ejs +121 -0
- package/src/views/releases/v1.9.0.ejs +111 -0
- package/src/views/releases/v2.0.0.ejs +159 -0
- package/src/views/releases/v2.1.0.ejs +121 -0
- package/src/views/releases/v2.1.1.ejs +106 -0
- package/src/views/releases/v2.1.2.ejs +84 -0
- package/src/views/releases/v2.2.0.ejs +115 -0
- package/src/views/releases/v2.2.1.ejs +102 -0
- package/src/views/releases/v2.3.0.ejs +121 -0
- package/src/views/releases/v2.3.1.ejs +100 -0
- package/src/views/releases/v2.3.2.ejs +102 -0
- package/src/views/releases/v2.3.3.ejs +97 -0
- package/src/views/releases/v2.4.0.ejs +114 -0
- package/src/views/releases/v2.5.0.ejs +51 -0
- package/src/views/releases/v2.6.0.ejs +35 -0
- package/src/views/releases/v2.7.0.ejs +32 -0
- package/src/views/releases/v2.8.0.ejs +36 -0
- package/src/views/releases/v2.8.1.ejs +7 -0
- package/src/views/releases/v2.8.2.ejs +26 -0
- package/src/views/releases/v2.9.0.ejs +32 -0
- package/src/views/releases/v2.9.1.ejs +10 -0
- package/src/views/releases.ejs +26 -0
- package/src/views/sitemap.ejs +36 -0
- 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 < 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> </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') -%>
|