1 | Mitm.js
|
2 | =======
|
3 | [![NPM version][npm-badge]](http://badge.fury.io/js/mitm)
|
4 | [npm-badge]: https://badge.fury.io/js/mitm.png
|
5 |
|
6 | Mitm.js is a library for Node.js to **intercept and mock** network **TCP** and
|
7 | **HTTP** connections. Mitm.js intercepts and gives you a `Net.Socket` to
|
8 | communicate as if you were the remote server. For **HTTP requests** it even
|
9 | gives you `Http.IncomingMessage` and `Http.ServerResponse` — just like you're
|
10 | used to when writing Node.js servers. Except there's no actual server running,
|
11 | it's all just _In-Process Interception™_.
|
12 |
|
13 | Intercepting connections and requests is **extremely useful to test and ensure
|
14 | your code does what you expect**. Assert on request parameters and send back
|
15 | various responses to your code without ever having to hit the real network.
|
16 | **Fast as hell** and **a lot easier to develop with than external test
|
17 | servers**.
|
18 |
|
19 | Mitm.js should work both on the stable Node **v0.10.24** and up and **v0.11.11**
|
20 | and up and has **automated tests** to ensure it will stay that way.
|
21 |
|
22 | **Note**: This is a fairly early release of Mitm.js, so it might not cover all
|
23 | use cases you may come across. I've developed this on a need-to basis for
|
24 | testing [Monday Calendar][monday]'s syncing, so if you find a use-case I haven't
|
25 | come across, please fling me an [email][email], a [tweet][twitter] or [create an
|
26 | issue][issues] on GitHub.
|
27 |
|
28 | ### Tour
|
29 | - Intercept both **TCP socket connections** (`Net.connect`) and **HTTP
|
30 | requests** (`Http.request` and `Https.request`).
|
31 |
|
32 | - Hooks to Node.js's network functions at a **very low level** with the goal of
|
33 | not having to patch existing classes and have everything behave as if bytes
|
34 | were arriving from the network.
|
35 |
|
36 | - Does *not* have any kitchen sink features or yet another API to assert on
|
37 | intercepted connections.
|
38 | That's a different responsibility handled better by assertion libraries
|
39 | (you'll do no better than to pick [Must.js][must] for that ;-).
|
40 |
|
41 | - Use an **API you already to know** to assert or respond to requests — Mitm.js
|
42 | gives you access to a vanilla `Net.Socket` to respond with:
|
43 |
|
44 | ```javascript
|
45 | mitm.on("connection", function(socket) { socket.write("Hello back!") })
|
46 |
|
47 | var socket = Net.connect(22, "example.org")
|
48 | socket.write("Hello!")
|
49 | socket.setEncoding("utf8")
|
50 | socket.read() // => "Hello back!"
|
51 | ```
|
52 |
|
53 | - When you do **HTTP or HTTPS** requests, Mitm.js gives you both
|
54 | a `Http.IncomingMessage` and `Http.ServerResponse` to play the server with.
|
55 | That means you'll be using an **API you're already familiar with**
|
56 | rather than yet another idiosyncratic domain specific language.
|
57 |
|
58 | Mitm.js comes very handy to ensure your code makes requests with the
|
59 | appropriate parameters:
|
60 | ```javascript
|
61 | mitm.on("request", function(req, res) {
|
62 | req.headers.authorization.must.equal("OAuth DEADBEEF")
|
63 | })
|
64 |
|
65 | Http.get("http://example.org")
|
66 | ```
|
67 |
|
68 | It's also useful to see if your code behaves as you'd expect if everything is
|
69 | not `200 OK`:
|
70 | ```javascript
|
71 | mitm.on("request", function(req, res) {
|
72 | res.statusCode = 402
|
73 | res.end("Pay up, sugar!")
|
74 | })
|
75 |
|
76 | Http.get("http://example.org", function(res) {
|
77 | res.setEncoding("utf8")
|
78 | res.statusCode // => 402
|
79 | res.on("data", console.log) // => "Pay up, sugar!"
|
80 | })
|
81 | ```
|
82 |
|
83 | `Http.IncomingMessage` and `Http.ServerResponse` are the same objects
|
84 | you get when you write Node.js HTTP servers with `Net.Server` or use a library
|
85 | like [Express.js][express].
|
86 |
|
87 | - **Developed with automated tests**. Yeah, I know, why should one list this
|
88 | a feature when writing tests is just a sign of professionalism and respect
|
89 | towards other developers? But in a world where so many libraries and
|
90 | "production" software are released without *any* tests, I like to point out
|
91 | that I even write tests for testing libraries. ;-)
|
92 |
|
93 | [must]: https://github.com/moll/js-must
|
94 | [express]: http://expressjs.com
|
95 |
|
96 |
|
97 | Installing
|
98 | ----------
|
99 | ```
|
100 | npm install mitm
|
101 | ```
|
102 |
|
103 | From v1.0.0 Mitm.js will follow [semantic versioning][semver], but until then,
|
104 | breaking changes may appear between minor versions (the middle number).
|
105 |
|
106 | [semver]: http://semver.org/
|
107 |
|
108 |
|
109 | Using
|
110 | -----
|
111 | Require Mitm.js and invoke it as a function to both create an instance of `Mitm`
|
112 | and enable intercepting:
|
113 | ```javascript
|
114 | var Mitm = require("mitm")
|
115 | var mitm = Mitm()
|
116 | ```
|
117 |
|
118 | Mitm.js will then intercept all requests until you disable it:
|
119 | ```javascript
|
120 | mitm.disable()
|
121 | ```
|
122 |
|
123 | ### Intercepting in tests
|
124 | In tests, it's best to use the _before_ and _after_ hooks to enable and disable
|
125 | intercepting for each test case:
|
126 | ```javascript
|
127 | beforeEach(function() { this.mitm = Mitm() })
|
128 | afterEach(function() { this.mitm.disable() })
|
129 | ```
|
130 |
|
131 | ### Intercepting TCP connections
|
132 | After you've called `Mitm()`, Mitm.js will intercept and emit `connection` on
|
133 | itself for each new connection.
|
134 | The `connection` event will be given a server side `Net.Socket` for you to reply
|
135 | with:
|
136 |
|
137 | ```javascript
|
138 | mitm.on("connection", function(socket) { socket.write("Hello back!") })
|
139 |
|
140 | var socket = Net.connect(22, "example.org")
|
141 | socket.write("Hello!")
|
142 | socket.setEncoding("utf8")
|
143 | socket.read() // => "Hello back!"
|
144 | ```
|
145 |
|
146 | ### Intercepting HTTP/HTTPS requests
|
147 | After you've called `Mitm()`, Mitm.js will intercept and emit `request` on itself for each new HTTP or HTTPS request.
|
148 | The `request` event will be given a server side `Http.IncomingMessage` and
|
149 | `Http.ServerResponse`.
|
150 |
|
151 | For example, asserting on HTTP requests would look something like this:
|
152 | ```javascript
|
153 | mitm.on("request", function(req, res) {
|
154 | req.headers.authorization.must.equal("OAuth DEADBEEF")
|
155 | })
|
156 |
|
157 | Http.get("http://example.org")
|
158 | ```
|
159 |
|
160 | Responding to requests is just as easy and exactly like you're used to from
|
161 | using Node.js HTTP servers (or from libraries like [Express.js][express]):
|
162 | ```javascript
|
163 | mitm.on("request", function(req, res) {
|
164 | res.statusCode = 402
|
165 | res.end("Pay up, sugar!")
|
166 | })
|
167 |
|
168 | Http.get("http://example.org", function(res) {
|
169 | res.statusCode // => 402
|
170 | res.setEncoding("utf8")
|
171 | res.on("data", console.log) // => "Pay up, sugar!"
|
172 | })
|
173 | ```
|
174 |
|
175 | Please note that HTTPS requests are currently "morphed" into HTTP requests.
|
176 | That's to save us from having to set up certificates and disable their
|
177 | verification. But if you do need to test this, please ping me and we'll see if
|
178 | we can get Mitm.js to support that.
|
179 |
|
180 |
|
181 | Events
|
182 | ------
|
183 | All events that Mitm will emit on an instance of itself (see [Using
|
184 | Mitm.js](#using) for examples):
|
185 |
|
186 | Event | Description
|
187 | -----------|------------
|
188 | connect | Emitted when a TCP connection is made.<br> Given the client side `Net.Socket`.
|
189 | connection | Emitted when a TCP connection is made.<br> Given the server side `Net.Socket`.
|
190 | request | Emitted when a HTTP/HTTPS request is made.<br> Given the server side `Http.IncomingMessage` and `Http.ServerResponse`.
|
191 |
|
192 |
|
193 | License
|
194 | -------
|
195 | Mitm.js is released under a *Lesser GNU Affero General Public License*, which
|
196 | in summary means:
|
197 |
|
198 | - You **can** use this program for **no cost**.
|
199 | - You **can** use this program for **both personal and commercial reasons**.
|
200 | - You **do not have to share your own program's code** which uses this program.
|
201 | - You **have to share modifications** (e.g. bug-fixes) you've made to this
|
202 | program.
|
203 |
|
204 | For more convoluted language, see the `LICENSE` file.
|
205 |
|
206 |
|
207 | About
|
208 | -----
|
209 | **[Andri Möll][moll]** typed this and the code.
|
210 | [Monday Calendar][monday] supported the engineering work.
|
211 |
|
212 | If you find Mitm.js needs improving, please don't hesitate to type to me now
|
213 | at [andri@dot.ee][email] or [create an issue online][issues].
|
214 |
|
215 | [email]: mailto:andri@dot.ee
|
216 | [issues]: https://github.com/moll/js-mitm/issues
|
217 | [moll]: http://themoll.com
|
218 | [monday]: https://mondayapp.com
|
219 | [twitter]: https://twitter.com/theml
|