Simple jetty server to record HTTP requests.

URLs

Do you want to improve this page? Please edit it on GitHub.

Description

http-request-recorder is a small tool that can be used to record HTTP requests. It is based on Eclipse Jetty and runs on the JVM. Recorded requests are available in memory (as RxJava stream), can be printed in the console or stored as JSON file on the disk.

Download

Binaries are hosted on maven central.

core

Maven coordinates of the 'core' project (xml notation)
<dependency>
  <groupId>com.unblu.tools</groupId>
  <artifactId>http-request-recorder-core</artifactId>
  <version>4.0.0</version>
</dependency>
Maven coordinates of the 'core' project (single line notation)
"com.unblu.tools:http-request-recorder-core:4.0.0"

cli

Maven coordinates of the 'cli' project (xml notation)
<dependency>
  <groupId>com.unblu.tools</groupId>
  <artifactId>http-request-recorder-cli</artifactId>
  <version>4.0.0</version>
</dependency>
Maven coordinates of the 'cli' project (single line notation)
"com.unblu.tools:http-request-recorder-cli:4.0.0"

cli (fat jar)

A standalone jar (containing the dependencies) is also published:

Maven coordinates of the 'cli fat jar' (xml notation)
<dependency>
  <groupId>com.unblu.tools</groupId>
  <artifactId>http-request-recorder-cli</artifactId>
  <version>4.0.0</version>
  <classifier>all</classifier>
</dependency>
Maven coordinates of the 'cli fat jar' (single line notation)
"com.unblu.tools:http-request-recorder-cli:4.0.0:all"

Usage

cli

You can start the server with:

java -jar libs/hrr.jar --log

Some usefull flags:

--log: each request will be logged into the console

--port: a fixed port for the server will be used

--output: stores each request as json file (see example bellow). The --tree flag can be usefull to influence the way the files are stored.

Usage example:

Started with:

java -jar libs/hrr.jar --port 8090 --output out

For following requests:

GET http://localhost:8090/service1/ping
POST http://localhost:8090/service1/ping
POST http://localhost:8090/service1/check
GET http://localhost:8090/service2

You will get one file per request in the out/ folder:

out/1542289573057-service1_ping.json
out/1542289576028-service1_ping.json
out/1542289591111-service1_check.json
out/1542289607227-service2.json

With the --tree flag the requested URI is used to separate the files in subfolders that correspond to the file. The same requests will produce:

out
|____service1
| |____ping
| | |____1542289573057.json
| | |____1542289576028.json
| |____check
|   |____1542289591111.json
|____service2
  |____1542289607227.json

Help:

You can see the list of the flags with:

java -jar libs/hrr.jar --help

core

The core can be embedded in an other java application (for example when used during some unit-tests).

Just include com.unblu.tools:http-request-recorder-core:$hrrVersion as test dependency.

With server being a com.unblu.tools.hrr.core.JettyServer instance (that is created and started before the test execution and stopped after the test), a simple test can look like this:

//Access the request recorder:
Observable<RequestRecord> observable$ = server.onRequest();

//create test observer
TestObserver<RequestRecord> testObserver = observable$.test();

//Simple subscription: log the HTTP record as INFO log
observable$.map(RequestRecordConverter::asLog).subscribe(LOG::info);

//Perform a GET Request:
HttpURLConnection con = performPinGetRequest();

//Perform assertions on the server response:
int status = con.getResponseCode();
assertThat(status).isEqualTo(200);
String content = new BufferedReader(new InputStreamReader(con.getInputStream())).lines().collect(Collectors.joining("\n"));
assertThat(content).isEqualTo("{ \"status\": \"ok\"}");

//Perform assertions on the recorded server event:
testObserver.assertNoErrors().assertValueCount(1).assertValueAt(0, record -> {
        assertThat(record.getMethod()).isEqualTo("GET");
        assertThat(record.getRequestURI()).isEqualTo("/ping");
        return true;
});

In this case onRequest is used, which only emits for events that happen after subscription.

Use getRequest to also get the last previous one:

//Access the request recorder:
Observable<RequestRecord> observable$ = server.getRequest();

//Perform a GET Request:
HttpURLConnection con = performPinGetRequest();

//Simple subscription: log the HTTP record as INFO log
//Retrieves still the last record
observable$.map(RequestRecordConverter::asLog).subscribe(LOG::info);

//Perform assertions on the server response:
int status = con.getResponseCode();
assertThat(status).isEqualTo(200);
String content = new BufferedReader(new InputStreamReader(con.getInputStream())).lines().collect(Collectors.joining("\n"));
assertThat(content).isEqualTo("{ \"status\": \"ok\"}");

//Perform assertions on the recorded server event:
observable$.test().assertNoErrors().assertValueCount(1).assertValueAt(0, record -> {
        assertThat(record.getMethod()).isEqualTo("GET");
        assertThat(record.getRequestURI()).isEqualTo("/ping");
        return true;
});

With JUnit 5 the server can be managed like this (this is only one example, you might prefer to manage the server globally somewhere else)

Start the server before all tests in the class.
@BeforeAll
public static void before() throws Exception {
        server = new JettyServer();
        server.start();
}
Stop the server after all tests in the class.
@AfterAll
public static void after() throws Exception {
        server.stop();
}

Development

This project is tested with Eclipse IDE, it should however work with any other IDE as well.

Build

Build sources:

./gradlew build

Deploy to maven local:

./gradlew publishToMavenLocal

Build the documentation page:

./gradlew asciidoctor

Upload the documentation page on GitHub pages:

./gradlew gitPublishPush

Perform a release:

./gradlew release -Prelease.useAutomaticVersion=true

Using ssh-agent

Some tasks requires to push into the distant git repository (release task or updating the gh-pages branch). If they are failing with errors like this:

org.eclipse.jgit.api.errors.TransportException: ... Permission denied (publickey).

Then ssh-agent can be used.

eval `ssh-agent -s`
ssh-add ~/.ssh/id_rsa

(source for this approach)

Run the cli using Gradle

To run the cli project using gradle:

./gradlew cli:run --args ' --port 8090 --log'
./gradlew cli:run --args ' --help'

Get in touch

Use the issue tracker on GitHub.

You can also contact me on Twitter: @j2r2b

License