• Stars
    star
    635
  • Rank 68,455 (Top 2 %)
  • Language
    JavaScript
  • License
    Other
  • Created about 10 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Intercept and mock outgoing Node.js network TCP connections and HTTP requests for testing. Intercepts and gives you a Net.Socket, Http.IncomingMessage and Http.ServerResponse to test and respond with. Super useful when testing code that hits remote servers.

Mitm.js

NPM version Build status

Mitm.js is a library for Node.js (and Io.js) to intercept and mock outgoing network TCP and HTTP connections. Mitm.js intercepts and gives you a Net.Socket to communicate as if you were the remote server. For HTTP requests it even gives you Http.IncomingMessage and Http.ServerResponse — just like you're used to when writing Node.js servers. Except there's no actual server running, it's all just In-Process Interception™.

Intercepting connections and requests is extremely useful to test and ensure your code does what you expect. Assert on request parameters and send back various responses to your code without ever having to hit the real network. Fast as hell and a lot easier to develop with than external test servers.

Mitm.js works on all Node versions: ancient v0.10, v0.11 and v0.12 versions, previous and current LTS versions like v4 to v12 and the newest v13 and beyond. For all it has automated tests to ensure it will stay that way.

I've developed Mitm.js on a need-to basis for testing Monday Calendar's syncing, so if you find a use-case I haven't come across, please fling me an email, a tweet or create an issue on GitHub.

Tour

  • Intercept both TCP socket connections (Net.connect) and HTTP requests (Http.request and Https.request).

  • Hooks to Node.js's network functions at a very low level with the goal of not having to patch existing classes and have everything behave as if bytes were arriving from the network.

  • Does not have any kitchen sink features or yet another API to assert on intercepted connections.
    That's a different responsibility handled better by assertion libraries (you'll do no better than to pick Must.js for that ;-).

  • Use an API you already know to assert or respond to requests — Mitm.js gives you access to a vanilla Net.Socket to respond with:

    mitm.on("connection", function(socket) { socket.write("Hello back!") })
    
    var socket = Net.connect(22, "example.org")
    socket.write("Hello!")
    socket.setEncoding("utf8")
    socket.on("data", console.log) // => "Hello back!"
  • When you do HTTP or HTTPS requests, Mitm.js gives you both a Http.IncomingMessage and Http.ServerResponse to play the server with. That means you'll be using an API you're already familiar with rather than yet another idiosyncratic domain specific language.

    Mitm.js comes very handy to ensure your code makes requests with the appropriate parameters:

    mitm.on("request", function(req, res) {
      req.headers.authorization.must.equal("OAuth DEADBEEF")
    })
    
    Http.get("http://example.org")

    It's also useful to see if your code behaves as you'd expect if everything is not 200 OK:

    mitm.on("request", function(req, res) {
      res.statusCode = 402
      res.end("Pay up, sugar!")
    })
    
    Http.get("http://example.org", function(res) {
      res.setEncoding("utf8")
      res.statusCode // => 402
      res.on("data", console.log) // => "Pay up, sugar!"
    })

    Http.IncomingMessage and Http.ServerResponse are the same objects you get when you write Node.js HTTP servers with Net.Server or use a library like Express.js.

  • Bypass interception selectively for some connections (such as your SQL server) and let them connect as usual.

    mitm.on("connect", function(socket, opts) {
      if (opts.host == "sql.example.org" && opts.port == 5432) socket.bypass()
    })
  • Developed with automated tests. Yeah, I know, why should one list this a feature when writing tests is just a sign of professionalism and respect towards other developers? But in a world where so many libraries and "production" software are released without any tests, I like to point out that I even write tests for testing libraries. ;-)

Installing

npm install mitm

From v1.0.0 Mitm.js will follow semantic versioning, but until then, breaking changes may appear between minor versions (the middle number).

Using

Require Mitm.js and invoke it as a function to both create an instance of Mitm and enable intercepting:

var Mitm = require("mitm")
var mitm = Mitm()

Mitm.js will then intercept all requests until you disable it:

mitm.disable()

Intercepting in tests

In tests, it's best to use the before and after hooks to enable and disable intercepting for each test case:

beforeEach(function() { this.mitm = Mitm() })
afterEach(function() { this.mitm.disable() })

Intercepting TCP connections

After you've called Mitm(), Mitm.js will intercept and emit connection on itself for each new connection.
The connection event will be given a server side Net.Socket for you to reply with:

mitm.on("connection", function(socket) { socket.write("Hello back!") })

var socket = Net.connect(22, "example.org")
socket.write("Hello!")
socket.setEncoding("utf8")
socket.on("data", console.log) // => "Hello back!"

Intercepting HTTP/HTTPS requests

After you've called Mitm(), Mitm.js will intercept and emit request on itself for each new HTTP or HTTPS request.
The request event will be given a server side Http.IncomingMessage and Http.ServerResponse.

For example, asserting on HTTP requests would look something like this:

mitm.on("request", function(req, res) {
  req.headers.authorization.must.equal("OAuth DEADBEEF")
})

Http.get("http://example.org")

Responding to requests is just as easy and exactly like you're used to from using Node.js HTTP servers (or from libraries like Express.js):

mitm.on("request", function(req, res) {
  res.statusCode = 402
  res.end("Pay up, sugar!")
})

Http.get("http://example.org", function(res) {
  res.statusCode // => 402
  res.setEncoding("utf8")
  res.on("data", console.log) // => "Pay up, sugar!"
})

Please note that HTTPS requests are currently "morphed" into HTTP requests. That's to save us from having to set up certificates and disable their verification. But if you do need to test this, please ping me and we'll see if we can get Mitm.js to support that.

Custom HTTP Methods

Unfortunately because Node.js's web server doesn't seem to support custom HTTP methods (that is, ones beyond require("http").METHODS), Mitm.js doesn't support them out of the box either. The Node.js HTTP parser throws an error given a request with an unsupported method. However, as Mitm.js also supports intercepting at the TCP level, you could hook in your own HTTP parser. I've briefly alluded to it in issue #63.

Bypassing interception

You can bypass connections listening to the connect event on the Mitm instance and then calling bypass on the given socket. To help you do so selectively, connect is given the options object that was given to Net.connect:

mitm.on("connect", function(socket, opts) {
  if (opts.host == "sql.example.org" && opts.port == 5432) socket.bypass()
})

Bypassed connections do not emit connection or request events. They're ignored by Mitm.js.

In most cases you don't need to bypass because by the time you call Mitm in your tests to start intercepting, all of the long-running connections, such as database or cache connections, are already made.

You might need to bypass connections you make to localhost when you're running integration tests against the HTTP server you started in the test process, but still want to intercept some other connections that this request might invoke.
The following should suffice:

mitm.on("connect", function(socket, opts) {
  if (opts.host == "localhost") socket.bypass()
})

Events

All events that Mitm will emit on an instance of itself (see Using Mitm.js for examples):

Event Description
connect Emitted when a TCP connection is made.
Given the client side Net.Socket and options from Net.connect.
connection Emitted when a TCP connection is made.
Given the server side Net.Socket and options from Net.connect.
request Emitted when a HTTP/HTTPS request is made.
Given the server side Http.IncomingMessage and Http.ServerResponse.

License

Mitm.js is released under a Lesser GNU Affero General Public License, which in summary means:

  • You can use this program for no cost.
  • You can use this program for both personal and commercial reasons.
  • You do not have to share your own program's code which uses this program.
  • You have to share modifications (e.g. bug-fixes) you've made to this program.

For more convoluted language, see the LICENSE file.

About

Andri Möll typed this and the code.
Monday Calendar supported the engineering work.

If you find Mitm.js needs improving, please don't hesitate to type to me now at [email protected] or create an issue online.

More Repositories

1

vim-node

Tools and environment to make Vim superb for developing with Node.js. Like Rails.vim for Node.
Ruby
808
star
2

vim-bbye

Delete buffers and close files in Vim without closing your windows or messing up your layout. Like Bclose.vim, but rewritten and well maintained.
Vim Script
637
star
3

json-stringify-safe

Like JSON.stringify, but doesn't throw on circular references
JavaScript
543
star
4

js-must

An assertion library for JavaScript and Node.js with a friendly BDD syntax (awesome.must.be.true()). It ships with many expressive matchers and is test runner and framework agnostic. Follows RFC 2119 with its use of MUST. Good stuff and well tested.
JavaScript
334
star
5

capistrano-rsync

Deploy with Rsync from any local (or remote) repository when using Capistrano. Capistrano v3 ready!
Ruby
125
star
6

js-ddl

Gets you a JSON Schema from PostgreSQL or SQLite3. Also supports arrays and default values. Use it for introspection or preparing your domain models like with Rails's Active Record.
JavaScript
68
star
7

js-fetch-defaults

Fetch API mixin to set a default base URL and options. Functional and immutable.
JavaScript
55
star
8

mina-rsync

Deploy with Rsync from any local (or remote) repository when using Mina.
Ruby
50
star
9

js-concert

An event library for JavaScript and Node.js that implements the observer pattern (a.k.a publish/subscribe). Similar to Node's EventEmitter and Backbone.Events, but independent, minimal and light-weight.
JavaScript
43
star
10

js-standard-error

Tiny JavaScript library that simplifies subclassing and inheriting from Error while keeping the correct name and stack. Also supports constructing from an object of properties. Saves you from boilerplate.
JavaScript
41
star
11

js-undersign

A JavaScript library for creating eIDAS compatible XAdES signatures, incl. support for OCSP, timestamps and ASIC-E. Works also with the Estonian Id-card, Mobile-Id and Smart-Id out of the box.
JavaScript
29
star
12

js-strange

Range object for JavaScript. Supports exclusive and infinite ranges. Stringifies to PostgreSQL compatible format.
JavaScript
26
star
13

node-pg-error

An error class for Node.js that parses PostgreSQL's ErrorResponse format and sets human readable field names. Works with node-pg, too.
JavaScript
22
star
14

sh-chnode

Change between installed Node versions in your current shell.
Shell
22
star
15

js-promise-defer

JavaScript Polyfill for Promise.defer. Uses the native ES6 Promise. Supports other Promises/A+ implementations.
JavaScript
22
star
16

js-standard-http-error

Standard HTTP error class for Node.js. Proper serialization, no bloat. Extensible.
JavaScript
19
star
17

js-element-from-point

A consistent cross-browser document.elementFromPoint function. Works around idiosyncracies of old WebKits et al.
Makefile
11
star
18

node-require-guard

Prevent files and modules being required more than once. Helps with auto-reloaders or test runners that insist.
JavaScript
9
star
19

js-oolong

Object utility library for JavaScript. Simple, tasteful and plentiful. Supports inherited properties.
JavaScript
8
star
20

js-hugml

An XML parsing and serializing library based on Google's GDATA and BadgerFish conventions. Supports namespaces.
JavaScript
7
star
21

js-j6pack

JavaScript library to render JSX to JavaScript and HTML on the web or on Node.js. Works with Express.js. No React dependency, no virtual DOM.
JavaScript
7
star
22

js-co-next

JavaScript function to use generators for request handlers and middleware. Calls next only if there was an error. Useful for Express routes.
JavaScript
7
star
23

js-internet-message

Library for JavaScript to parse and stringify RFC 822 ARPA Internet Text Messages. Useful format for messages with headers and body. Similar to HTTP.
JavaScript
6
star
24

js-sqlate

A tiny tagged template string function library for JavaScript to write SQL safely. Works with Mapbox's SQLite3 library, Brian Carlson's PostgreSQL library and others.
JavaScript
6
star
25

js-lazy-object

JavaScript library to define lazy properties on objects that are initialized once and only when accessed. Also known as a lazy initialization and cached/memoized getters.
JavaScript
6
star
26

js-medium-type

JavaScript library for parsing, stringifying and manipulating media types. Useful for content negotiation. Follows RFC2045, supports quoted parameters, all allowed characters etc.
JavaScript
5
star
27

js-kindof

A proper typeof that works with primitives, built-in value objects and those from other execution contexts.
JavaScript
5
star
28

js-syslog-protocol

Syslog (RFC 3164) parser. Works with RFC 3339/ISO 8601 timestamps.
JavaScript
5
star
29

nutikaitse

CSS
5
star
30

js-fetch-parse

Fetch API mixin to buffer and parse response bodies. Supports media type patterns for content type specific custom parsers.
JavaScript
4
star
31

node-selenium-dom

SeleniumDom.js is a mixin library for Node.js's Selenium WebDriver that adds **DOM methods** to Selenium's `WebDriver` and `WebElement`.
JavaScript
4
star
32

js-square-batman

A small JavaScript scheduling algorithm library. Useful for round-robin etc.
JavaScript
4
star
33

js-fetch-jsonify

Fetch API mixin for stringifying JSON and setting Content-Type if unset. Functional and immutable.
JavaScript
3
star
34

js-egal

Strict equality test (like ===) for JavaScript that handles both built-in and custom value objects (those with a valueOf function).
JavaScript
3
star
35

node-syslogh

Log to your system's Syslog from within Node.js. Provides simple native bindings to <syslog.h> and syslog(3). Works on Node v0.10 up to v4 and beyond.
C++
3
star
36

browserify-substitution-mass-confusion

Browserify plugin for substituting modules everywhere. It expands the package.json "browser" field to work for nested dependencies.
JavaScript
3
star
37

node-fetch-off

Fetch API polyfill and facade. Its request and response wrappers can be used separately: use fetch for request yet get back Node's Http.get response (IncomingMessage) for streaming.
JavaScript
2
star
38

js-internet-message-type

Library for JavaScript to parse RFC 822 ARPA Internet Text Messages types and bodies. Works well with InternetMessage.js.
JavaScript
2
star
39

exportjs

A tool that helps you publish and export your JavaScripts to other environments by wrapping them in an IIFE. Or UMD in the future.
JavaScript
1
star
40

js-fetch-error

A JavaScript library for an error class for use with the Fetch API.
JavaScript
1
star
41

js-soul

Soul.js is a simple yet extensible mutable model library for JavaScript.
JavaScript
1
star
42

js-descend

Function to set up an inherited class that calls its ancestor constructors automatically. Can also be attached to constructors.
JavaScript
1
star
43

js-fetch-throw

A JavaScript Fetch API mixin to throw FetchError when the request fails or response has an error.
JavaScript
1
star
44

node-flash-fiction

Flash messages middleware for Express/Connect with support for redirects and immediate use. Useful for informational or errors messages. Like Rails's Flash.
JavaScript
1
star
45

js-overstrike

A utility library in the style of Underscore.js with consistent inherited property handling, the simplest implementation and curation by yours truly.
JavaScript
1
star
46

js-fetch-formify

Fetch API mixin for urlencoding an object and setting Content-Type if unset. Functional and immutable.
JavaScript
1
star