CURL Logger

Build Status Maven Central

Logs HTTP requests sent by REST-assured as CURL commands.

The following request from REST-assured test

given()
  .config(config)
  .redirects().follow(false)
.when()
  .get("http://google.com")
.then()
  .statusCode(302); 

will be logged as:

curl 'http://google.com/' -H 'Accept: */*' -H 'Content-Length: 0'  -H 'Connection: Keep-Alive' 
  -H 'User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_112)' -H 'Content-Type: multipart/mixed' 
  --compressed -k -v

This way testers and developers can quickly reproduce an issue and isolate its root cause.

Usage

Latest release:

<dependency>
  <groupId>com.github.dzieciou.testing</groupId>
  <artifactId>curl-logger</artifactId>
  <version>1.0.5</version>
</dependency>

Using with REST-assured client

When sending HTTP Request with REST-assured, you must create RestAssuredConfig instance first as follows:

RestAssuredConfig config = CurlLoggingRestAssuredConfigFactory.createConfig();  

and then use it:

given()
  .config(config)
  ...

If you already have a RestAssuredConfig instance, you may reconfigure it as follows:

RestAssuredConfig config = ...;
config = CurlLoggingRestAssuredConfigFactory.updateConfig(config);  

The library provides a number of options for the way curl is generated and logged. They can be defined with Options class. For instance:

Options options = Options.builder()...build();
RestAssuredConfig config = CurlLoggingRestAssuredConfigFactory.createConfig(options);  

There is a separate section listing all options.

Configuring logger

CURL commands are logged to a "curl" logger. The library requires only the logger to be slf4j-compliant, e.g., using logback. Sample logback configuration that logs all CURL commands to standard system output would be:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>
    <logger name="curl" level="DEBUG">
        <appender-ref ref="STDOUT"/>
    </logger>
</configuration>

Options

Printing stacktrace

The library provides a way to log stacktrace where the curl was generated:

Options.builder().logStacktrace().build();

This might be particularly useful when your test is sending multiple requests and you cannot find which request generated printed curl command.

By default CurlLoggingRestAssuredConfigFactory#createConfig creates configuration that prints a curl command in a single line.

Generating curl for Windows vs Unix

The curl command generated by the library is platform-specific.

For instance, curl command generated for Unix platform

curl 'http://testapi.com/post' --data-binary $'{\r\n   \'name\':\'Administra\xe7\xe3o\',\r\n   
  \'email\':\'admin\x40gmail.com\',\r\n   \'password\':\'abc%"\'\r\n}'

will look different when generated for Windows platform:

curl "http://testapi.com/post" --data-binary "{"^

"   'name':'Administração',"^

"   'email':'[email protected]',"^

"   'password':'abc"%"""'"^

"}"

The difference is in:

By default, the library assumes the target platform on which curl command will be executed is the same as the platform where it was generated. However, when you work on two different platforms, sometimes a curl command generated on Unix might not be portable to Windows, and vice-versa.

In such situations, the library provides a way to force target platform, e.g.,:

Options.builder().targetPlatform(Platform.UNIX).build();

Even if origin and target platform are the same, some characters must be escaped, because the generated curl command will be copy-pasted on a multitude of setups by a wide range of people. I don't want the result to vary based on people's local encoding or misconfigured terminals. The downside of this might be less legible commands like Administra\xe7\xe3o instead of Administração. If you want your commands to be more legible (and bound to specific terminal setups) you may disable escaping non-ASCII characters by using the following option (for Unix only):

Options.builder().dontEscapeNonAscii().build();

Printing curl in multiple lines

The library enables printing a curl command in multiple lines:

Options.builder().printMultiliner().build();

On Unix systems it will look like this:

curl 'http://google.pl/' \ 
  -H 'Content-Type: application/x-www-form-urlencoded' \ 
  --data-binary 'param1=param1_value&param2=param2_value' \ 
  --compressed \ 
  -k \ 
  -v

and on Windows:

curl 'http://google.pl/' ^ 
  -H 'Content-Type: application/x-www-form-urlencoded' ^ 
  --data-binary 'param1=param1_value&param2=param2_value' ^ 
  --compressed ^ 
  -k ^ 
  -v

Logging request body

Note, for either platform, the body of a request is always logged as --binary-data instead of --data because the latter strips newline (\n) and carriage return (\r) characters.

Printing curl parameters in long form

The library enables printing longer form of curl parameters, e.g. --header instead of -H:

Options.builder().useLongForm().build();

Here's an example of a curl command generated with parameters in default short form (note, not all parameters have corresponding short form):

curl 'http://google.pl/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Host: google.pl' 
  -H 'User-Agent: 'User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_112)' 
  -H 'Connection: Keep-Alive' --data-binary 'param1=param1_value&param2=param2_value' --compressed -k -v

After enabling long form option it would look as follows:

curl 'http://google.pl/' -header 'Content-Type: application/x-www-form-urlencoded' 
  --header 'Host: google.pl'  --header 'User-Agent: 'User-Agent: Apache-HttpClient/4.5.2 
     (Java/1.8.0_112)' --header 'Connection: Keep-Alive' 
  --data-binary 'param1=param1_value&param2=param2_value' --compressed --insecure --verbose

By default CurlLoggingRestAssuredConfigFactory#createConfig create configuration that prints a curl command parameters in short form.

Updating curl command before print

The library provides a way to modify curl command before printing:

Options.builder().updateCurl(curl -> ...).build();

#updateCurl method takes instance of Consumer<CurlCommand> class. CurlCommand is a mutable representation of curl and offers a number of methods to modify it: #addHeader, #removeHeader, etc.

This is useful to:

For instance, if you would like skip common headers like "Host", "User-Agent" and "Connection" from the following curl command:

curl 'http://google.pl/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Host: google.pl'  
  -H 'User-Agent: 'User-Agent: Apache-HttpClient/4.5.2 (Java/1.8.0_112)' 
  -H 'Connection: Keep-Alive'  --data-binary 'param1=param1_value&param2=param2_value' --compressed -k -v

you should define Options as follows:

Options.builder()
  .updateCurl(curl -> curl
    .removeHeader("Host")
    .removeHeader("User-Agent")
    .removeHeader("Connection"))
  .build();

As a result it will generate the following curl:

curl 'http://google.pl/' -H 'Content-Type: application/x-www-form-urlencoded' 
  --data-binary 'param1=param1_value&param2=param2_value' --compressed -k -v

Other features

Logging attached files

When you attach a file to your requests via multiPart, e.g., sending content of "README.md" file

given()
  .config(new CurlLoggingRestAssuredConfigFactory.create)
  .baseUri("http://someHost.com")
  .multiPart("myfile", new File("README.md"), "application/json")
.when()
  .post("/uploadFile");

the library will automatically include reference to it instead of pasting its content:

curl 'http://somehost.com/uploadFile' -F '[email protected];type=application/json' -X POST ...

Note, this won't work when uploading File not via multipart. Instead, content of the file will be printed.

given()
  .config(new CurlLoggingRestAssuredConfigFactory.create)
  .baseUri("http://someHost.com")
  .body(new File("README.md"))
.when()
  .post("/uploadFile");

Prerequisities

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>
<dependency>
    <groupId>io.restassured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>4.0.0</version>
</dependency>

Releases

1.0.5:

1.0.4:

1.0.3:

1.0.2:

1.0.1:

1.0.0:

0.7:

0.6:

0.5:

0.4:

0.3:

0.2:

0.1:

Similar tools

Bugs and features request

Report or request in Issues.

Contribute!

This is an open-source library, and contributions are welcome. You're welcome to fork this project and send me a pull request.

Supporting

This is an open-source library that I give for free to the community as my way of saying thank you for all the support I have received from this community.

If you like my work and want to say thank you as well then:

Buy me a coffee