bock
Next-generation browser HTTP traffic mocking, proxy, and request transformer with useful features such as inferred delays and more. It uses ServiceWorkers for a reliable and safe MITM-like network interceptor and provides an elegant, expressive and simple programmatic approach
Note that ServiceWorker is still an experimental technology and its standard is under active discussion and it is not currently supported by latest production browsers
Aditionally you should consider that this library is very much a work in progress, as it is a hacking-driven implementation, therefore important changes can be done in a near future and API retrocompatibility is not premise
If you are new with ServiceWorker, before getting started you could take a look to the explainer document, HTML5rocks introduction or the draft specification
Installation
Via Bower
bower install bock
Via Component
component install h2non/bock
Or loading the script remotely
<script src="//cdn.rawgit.com/h2non/bock/0.1.0-beta.1/bock.js"></script>
Setup
Due to ServiceWorkers security limitations, it's required to copy the bock.worker.js
source in the root directory of your application (although, you could use the HTTP server rewrite rules to do the same in remote servers) in order to be enable the Service Worker control into the desired page scope (defaults to /
)
Example command if you are using Bower as package manager
cp ./bower_components/bock/bock.worker.js .
Chrome Canary setup
To start hacking with ServiceWorker you should enable the "experimental Web Platform features" flag in Canary.
You can do it opening chrome://flags
. Then you should restart the browser
How to debug
Open chrome://serviceworker-internals/
, or alternatively use chrome://inspect/#service-workers
Browser Support
Canary ✔ | Nightly ✔ | No | ? | No |
Basic usage
Mocking
Basic request mocking and expectation
bock('http://www.google.com')
.get('/search')
.reply(200, 'Hello from Google!')
Define custom request headers and response body
bock('http://my.api.com')
.post('/users/1')
.headers({Â 'Content-Type': 'application/json' })
.replyWithHeaders({ 'Content-Type': 'text/xml' })
.replyWithBody('<xml><user><name>Chuck Norris</name></user></xml>')
.delay(100)
.reply(200)
Proxy
Basic request proxy
bock('http://my.api.com')
.get('/users/1')
.proxy('http://my.api.com/user/1')
.forward()
Custom request override with different method, headers and body
bock('http://my.api.com')
.get('/users/1')
.proxy('http://my.api.com/user/1')
.withMethod('POST')
.withHeaders({ Authorization: 'Bearer 0123456789' })
.withBody('Hello World')
.delay(100)
.forward()
Restoring
bock.cleanAll()
Checking Worker status
Due to ServiceWorker native limitations, you may need to reload the page in order to allow the worker can do the magic stuff
bock.isEnable() // -> true
Retrieving configured mocks/proxies
bock.entries() // -> [{ id: '123', config: { ... } ... }]
API
bock(baseUrl, [ options ])
Create a new Bock
mocking/proxy scope
Supported options are:
-
path
string
- Path tobock.worker.js
. Default to/bock.worker.js
-
scope
string
- Worker control path scope. Default to/
bock#get(path)
Intercept a GET request with the given URL path
bock#post(path)
Intercept a POST request with the given URL path
bock#put(path)
Intercept a PUT request with the given URL path
bock#delete(path)
Intercept a DELETE request with the given URL path
bock#head(path)
Intercept a HEAD request with the given URL path
bock#patch(path)
Intercept a PATCH request with the given URL path
bock#params(params)
Define the request params to match. Support is still in progress, use query search string at URI level instead
bock#body(body)
Define the request body to match. Note that body matching is currently not supported
bock#headers(headers)
Define the request headers to match
bock#auth(user, password)
Current not supported. Use Authorization
header instead
bock#delay(miliseconds)
Delay the response the given miliseconds
body#replyHeaders(headers)
Alias: replyWithHeaders()
Define custom headers to inject in the mock response
body#replyBody(body)
Alias: replyWithBody()
Define a custom body data to inject in the mock response
body#reply(code, [Â body, headers ])
Alias: replyWith()
Define the response status code to inject in the mock response, and optionally the response body and headers
bock#proxy(url, [ body, headers ])
Forward the matched request to another destination overriding the URL and optionally overriding a custom body and request headers
bock#withHeaders(headers)
Proxy mode only. Override the default request headers
bock#withMethod(method)
Proxy mode only. Override the default request method
bock#witBody(body)
Proxy mode only. Override the default request body
bock#credentials(type)
Proxy mode only. Define a custom request send credentials mode. See fetch specification
bock#forward()
Proxy mode only. Enable request forwarding. You must call this method to register a proxy request
bock.isEnabled()
Alias: isControllable()
Return true
if the ServiceWorker in currently controlling the current page
bock.cleanAll()
Disable and flush all mocks/proxy configurations. Restore to initial state
bock.entries()
Return a collection of the current active mocks/proxy configuration entries
bock.stop()
Stop and unregister the ServiceWorker in the current scope.
Please be aware that the ServiceWorker
livecycle is handled by the browser and it could persist if another tab/window is also using it
See the spec for more information
bock.workerPath
Type: string
Bock worker file path. Default to /bock.worker.js
.
Be aware with the scope
security limitations
bock.VERSION
Type: string
Current library semantic version
To Do list
- Support regular expressions for better versatility on URL pattern matching
- Smart body/payload matching for seriable data structures
- Workers <-> controlled pages scopes synchronization via
postMessage()
- Add config persistency (see IndexedDB)
- Reliable way to close/unregister a worker (see spec)
- Support for easily handling of cache
- Support for request transforming
- Better fallback handling
Contributing
Wanna help? Cool! It will be appreciated :)
You must add new test cases for any new feature or refactor you do, always following the same design/code patterns that already exist
Development
Only node.js is required for development
Clone the repository
$ git clone https://github.com/h2non/bock.git && cd bock
Install dependencies
$ npm install
Generate browser bundle source
$ make browser
Run tests
$ make test
See the examples
$ ./node_modules/.bin/http-server
License
MIT - Tomas Aparicio