Browse by type
Logs HTTP requests sent by [REST-assured][9] as [CURL][1] 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.
Latest release:
<dependency>
<groupId>com.github.dzieciou.testing</groupId>
<artifactId>curl-logger</artifactId>
<version>3.0.0</version>
</dependency>
When sending HTTP Request with REST-assured, you must create RestAssuredConfig instance first
as follows:
RestAssuredConfig config = CurlRestAssuredConfigFactory.createConfig();
and then use it:
given()
.config(config)
...
If you already have a RestAssuredConfig instance, you may reconfigure it as follows:
RestAssuredConfig config = ...;
config = CurlRestAssuredConfigFactory.updateConfig(config);
NOTE: The library updates httpClient attribute of a RestAssuredConfig instance, so your changes to this attribute will be overwritten. Also, if you modify htttpClient attribute after calling updateConfig() or createConfig() method, curl-logger will no longer log requests.
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 = CurlRestAssuredConfigFactory.createConfig(options);
There is a separate section listing all options.
CURL commands are logged to a "curl" logger. The library requires only the logger to be [slf4j][4]-compliant, e.g., using [logback][5]. 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>
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 CurlRestAssuredConfigFactory#createConfig creates configuration that prints a curl command without stacktrace.
There is a way to define at which log level the log statement should be created:
Options.builder().useLogLevel(Level.INFO).build();
By default the curl commands are generated at DEBUG level, but depending on the context it might
be handy to log at a higher level.
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@gmail.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':'admin@gmail.com',"^
" 'password':'abc"%"""'"^
"}"
The difference is in: - how strings are quoted, - how different characters (non-ASCII characters, non-printable ASCII characters and characters with special meaning) are escaped, - and how new lines in multiline command are printed.
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();
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¶m2=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¶m2=param2_value' ^
--compressed ^
-k ^
-v
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.
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¶m2=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¶m2=param2_value' --compressed --insecure --verbose
By default CurlRestAssuredConfigFactory#createConfig create configuration that prints
a curl command parameters in short form.
By default, curl-logger does not print HTTP method for GET requests and POST requests without data. To always print request method, method configure curl-logger as follows:
Options.builder().alwaysPrintMethod().build();
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: * modify generated curl to test different variations of the same case * remove certain headers or parameters to make curl command more consise and thus easier to read
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¶m2=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¶m2=param2_value' --compressed -k -v
By default generated curls are logged. However, there's a way to process curl by one or more custom
handlers by providing a list of custom handlers, implementing CurlHandler interface. For instance,
to store generated curls in a variable one could write:
final List<String> curls = new ArrayList<>();
CurlHandler handler = new CurlHandler() {
@Override
public void handle(String curl, Options options) {
curls.add(curl);
}
};
List<CurlHandler> handlers = Arrays.asList(handler);
CurlRestAssuredConfigFactory.createConfig(handlers)
When you attach a file to your requests via multiPart, e.g., sending content of "README.md" file
given()
.config(CurlRestAssuredConfigFactory.createConfig())
.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 'myfile=@README.md;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(CurlRestAssuredConfigFactory.createConfig())
.baseUri("http://someHost.com")
.body(new File("README.md"))
.when()
.post("/uploadFile");
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>io.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.2.0</version>
</dependency>
2.1.2: * Upgrade runtime dependencies: REST-assured from 4.4.0 to 5.2.0 * Escape "at" character (@) only when it is first character in request (#80)
2.1.1:
* Upgrade runtime dependencies: REST-assured from 4.3.12 to 4.4.0, httpclient from 4.5.3 to 4.5.13, Guava from 28.0-jre to 29.0-jre
* Upgrade development dependencies (to TestNG 7.4.0, mockito from 2.0.2-beta to 3.12.1)
* Fixed bug #74: Options.builder().updateCurl(curl -> curl.removeHeader("Cookie").build(); now correctly removes also Cookie header (thanks to @iamrulloh for reporting the problem)
2.1.0:
* Support for alwaysPrintMethod option that enables always printing HTTP method of a request (many thanks to Luigi
Cardito for his pull request)
2.0.1: * Bug fix: Do not reuse HTTP client instance across multiple/parallel requests (fix for #37) * Bug fix: Make CurlHandler interface public (fix for #56)
2.0.0:
* Fix to invalid escaping of characters longer than 8 bits (#47,
thanks to Srepfler Srdan for reporting it)
* Tested with latest REST-assured (4.3.1)
* Support for custom log levels (thanks to Jérémie Bresson for pull request)
* Support for custom curl handlers
* Backward-incompatible change: CurlLoggingRestAssuredConfigFactory renamed to
CurlRestAssuredConfigFactory.
1.0.5: * Upgrade to REST-assured 4.0.0. * Update test scope dependencies. * Bug fix: fix character escaping for both POSIX and Windows platforms (many thanks to Chirag008 for raising the issue: #25)
1.0.4: * Bug fix: HTTPS protocol was not always recognized correctly (#17). Many thanks to pafitchett-ks for troubleshooting. * Support slf4j 1.8.0-beta2. * Support rest-assured 3.2.0.
1.0.3: * Bug fix: Invalid basic authentication headers are failing curl generation (#15)
1.0.2: * Bug fix: CurlLogger was failing when multiple Cookie headers are present in HTTP Request. Now it only prints warning (#37)
1.0.1:
* Bug fix: CurlLoggingRestAssuredConfigBuilder was not updating RestAssuredConfig properly
(#4):
1.0.0:
CurlLoggingRestAssuredConfigBuilder replaced with
CurlRestAssuredConfigFactory that uses Options class to configure curl generation process.0.7:
$ claude mcp add curl-logger \
-- python -m otcore.mcp_server <graph>