Interception Script
netsleuth allows you to write interception scripts that are invoked for every HTTP request sent to a target. Your script can:
- Modify the request headers before the request is sent to the server
- Respond directly to the request (without sending the request to the target)
- Modify the response headers before the response is sent to the client
Scripts are located in ~/.config/netsleuth/script/*
. The script
folder contains a subfolder for each target. The JS files in those folders will be automatically loaded and watched for changes.
Note: at this time, interception scripts have two important limitations:
- It is not possible to read or modify the body of a request or response.
- Scripts only work on proxied targets. node.js native integration targets are not supported.
We plan to address these limitations in a future release.
To ensure they do not negatively impact performance, interception scripts run in their own thread. You generally have most node.js facilities available to you in your script, but a few caveats apply. Each netsleuth target gets its own script thread, which is shared by each script in that target's script folder.
Example
~/.config/netsleuth/script/127.0.0.2/example.js
host.on('request', function(req) { if (req.url == '/blockme') return false; // blocks the request else if (req.url == '/fake') req.respond(200, { fake: 'data' }); // sends a synthetic response else req.headers.rand = Math.random(); // modifies a request header });
Note: simple request blocking based on URL pattern matching can be also be achieved without writing script using the GUI's Request blocking tab.
API
host
Scripts have a global host
object that represents a target. Scripts are automatically associated with the target that matches its containing directory's name.
Event: 'request'
req
<Request>
represents the pending request
Emitted when a request is received from a client and before the request is forwarded to the target server. Any changes you make to req
's properties will be reflected in the request sent to the target server.
If the listener function returns a Promise
, the request will not be forwarded until the Promise
resolves. This means you can safely perform asynchronous operations (including using async
/await
).
If the listener function returns false
(or returns a Promise
that resolves to false
), then the request will be blocked by netsleuth. The target will never see the request and a the client will be sent a HTTP 450.
host.stopOnError
<boolean>
When an interception script's request or response event handler throws an error, this controls whether netsleuth stops the request and returns a 502 error to the client or ignores the error. Default: false
Request
Represents a pending request. Looks similar to a http.ClientRequest
, although it is not an exact implementation.
Event: 'response'
res
<Response>
Emitted when a response is received from the target server and before the response is forwarded to the client. Any changes you make to res
' properties will be reflected in the response sent to the client.
If the listener function returns a Promise
, the response will not be forwarded until the Promise
resolves. This means you can safely perform asynchronous operations (including using async
/await
).
If the listener function returns false
(or returns a Promise
that resolves to false
), then the target's response will be discarded and the client will be sent a HTTP 450.
request.protocol
<string>
The protocol that will be used to communicate with the target server. http:
or https:
.
request.method
<string>
The HTTP method of the request.
request.host
<string>
The host (including port) of the target server.
request.url
<string>
The request path.
request.httpVersion
<string>
The HTTP version number of the incoming request. Usually 1.1
.
request.headers
<object>
An object containing the request's headers.
request.respond([statusCode][, headers][, body])
statusCode
<integer>
headers
<object>
body
<string>
|<Buffer>
|<object>
|<undefined>
- Returns:
<Response>
Allows you to respond directly to the request, skipping the target server entirely.
If statusCode
is not supplied, it will default to 200
.
body
is passed to response.setBody()
; see its behavior notes. Currently, if body
is undefined
, this will throw. In a future release, the returned Response
will be a writable stream.
Response
Represents a HTTP response.
response.statusCode
<integer>
The HTTP response code.
response.statusMessage
<string>
The HTTP response status message.
response.headers
<object>
An object containing the response's headers.
response.setBody(body)
body
<string>
|<Buffer>
|<object>
This method's exact behavior depends on what you pass in to body
:
string
: theContent-Type
header is set totext/plain
, the string is sent to the client, and the response is ended.Buffer
: theBuffer
is sent to the client and the response is ended.object
: the object is passed toJSON.stringify
, theContent-Type
header is set toapplication/json
, the result sent to the client and the response is ended.