Writing a hooks handler for a new language
Several hooks handlers already exist, either maintained by Dredd authors or external contributors. If you didn’t find your favorite language among them, at this place you can learn how to create a new hooks handler.
Deserve eternal praise and contribute hooks handler for Java! See #875
What is a hooks handler?
Hooks handler is a process running separately from Dredd, usually started by Dredd as a child process when invoking Dredd with the
--language option. When Dredd performs testing, it communicates with the hooks handler over TCP socket. The hooks handler runs hooks for each HTTP transaction and lets Dredd know whether something got modified.
Hooks handler life cycle
Dredd starts the command given in the
--languageoption as its child process (subprocess). Paths to files with hooks given in
--hookfilesare resolved to absolute paths and given to the child process as arguments.
The hooks handler reads paths to hooks from arguments and loads the hooks code.
The hooks handler opens a TCP socket on localhost, port 61321.
Dredd waits for a moment and then tries to connect to localhost, port 61321.
For each type of hooks Dredd creates a message and sends it to the socket. The message contains UUID and serialized transaction object (or an array of them, in case of beforeAll, afterAll). Individual messages are sent as JSON documents separated by a newline.
Hooks handler reads a message, calls a corresponding hook code, and sends back a message with modified contents.
Dredd awaits a message with corresponding UUID. Once it arrives, Dredd overwrites its internal HTTP transaction data with the ones from the incoming message.
A hooks handler is a CLI command, which implements following:
It accepts paths to hook files as arguments. They are already passed resolved as absolute paths, in the right order.
It loads the hook files and registers any hook functions found in them for later execution.
It runs a TCP socket server on port 61321 and prints
When any data is received by the TCP server, the hooks handler:
Adds every received character to a buffer.
When the delimiter
LINE FEED (LF)character encoded as UTF-8 (
\nin most languages) is received:
Parses the message in the buffer as JSON.
Finds the hook type in the
eventkey of the received object and executes respective registered hook function(s). Beware,
afterEachare overloaded - read the TCP socket message format carefully.
When a hook function is being executed:
Passes the value of the
datakey of the received object to the executed hook function.
Allows the hook function to modify the data.
When a hook function is done:
Takes the modified data and serializes it back to JSON with the same
uuidas it has received
Sends the JSON back as a TCP message
LINE FEED (LF)character encoded as UTF-8 (
\nin most languages) as TCP message delimiter
TCP socket message format
234567-asdfghjkl(string) - ID used for unique identification of the message on both server and client sides
event(enum) - Hook type
beforeAll (string) - Signals the hooks handler to run the
beforeEach (string) - Signals the hooks handler to run the
beforeEachValidation (string) - Signals the hooks handler to run the
afterEach (string) - Signals the hooks handler to run the
afterAll (string) - Signals the hooks handler to run the
data (enum) - Data passed as an argument to the hook function
(object) - Single transaction object
(array) - An array of transaction objects, containing all transactions Dredd currently works with; sent for
When there is an error or when the testing is done, Dredd signals the hooks handler process to terminate. This is done repeatedly with delays. When termination timeout is over, Dredd loses its patience and kills the process forcefully.
retry delays can be configured by
timeout can be configured by
On Linux or macOS, Dredd uses the
SIGTERM signal to tell the hooks handler process it should terminate. On Windows, where signals do not exist, Dredd sends the
END OF TEXT character (
03 hex, which is ASCII representation of Ctrl+C) to standard input of the process.
End-to-end test suite
There is a BDD test suite called dredd-hooks-template, which ensures that the public interface of each hooks handler works as Dredd expects. The test suite is written in Gherkin and uses Cucumber as a test runner.
When developing a new hooks handler, make sure it passes the test suite. Third party hooks handlers not passing the test suite cannot be endorsed by Dredd maintainers, integrated with Dredd’s
--language option, or added to Dredd’s documentation.
If you have any issues integrating the test suite to your project, reach out to the maintainers in Dredd issues, we’re happy to help!
There are several configuration options, which can help you during development of the hooks handler:
Behavior of the following options is currently broken (see #917) and it is recommended to stick to localhost and port 61321 until fixed:
The options mention hooks worker in their names, but it stands for the same as hooks handler. There is a proposal to rename the options in the future: #1101