From d6a0167828b6d474d219c8406cc2fa5fb71d7127 Mon Sep 17 00:00:00 2001 From: Michal Moczulski Date: Sun, 21 Jan 2018 20:31:37 +0100 Subject: [PATCH 1/4] Added Options --- .../java/com/moczul/ok2curl/CurlBuilder.java | 7 +- .../com/moczul/ok2curl/CurlInterceptor.java | 25 +++++-- .../main/java/com/moczul/ok2curl/Options.java | 68 +++++++++++++++++++ .../java/com/moczul/ok2curl/OptionsTest.java | 58 ++++++++++++++++ .../ok2curl/util/HeaderModifierTest.java | 13 ++-- .../java/com/moczul/sample/MainActivity.java | 5 +- 6 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 ok2curl/src/main/java/com/moczul/ok2curl/Options.java create mode 100644 ok2curl/src/test/java/com/moczul/ok2curl/OptionsTest.java diff --git a/ok2curl/src/main/java/com/moczul/ok2curl/CurlBuilder.java b/ok2curl/src/main/java/com/moczul/ok2curl/CurlBuilder.java index 08c45bb..3d7dacc 100644 --- a/ok2curl/src/main/java/com/moczul/ok2curl/CurlBuilder.java +++ b/ok2curl/src/main/java/com/moczul/ok2curl/CurlBuilder.java @@ -30,15 +30,17 @@ public class CurlBuilder { private String method; private String contentType; private String body; + private List options; private List
headers = new LinkedList<>(); public CurlBuilder(Request request) { - this(request, -1L, Collections.emptyList()); + this(request, -1L, Collections.emptyList(), Options.EMPTY); } - public CurlBuilder(Request request, long limit, List headerModifiers) { + public CurlBuilder(Request request, long limit, List headerModifiers, Options options) { this.url = request.url().toString(); this.method = request.method(); + this.options = new ArrayList<>(options.list()); final RequestBody body = request.body(); if (body != null) { this.contentType = getContentType(body); @@ -106,6 +108,7 @@ private Charset getCharset(MediaType mediaType) { public String build() { List parts = new ArrayList<>(); parts.add("curl"); + parts.addAll(options); parts.add(String.format(FORMAT_METHOD, method.toUpperCase())); for (Header header : headers) { diff --git a/ok2curl/src/main/java/com/moczul/ok2curl/CurlInterceptor.java b/ok2curl/src/main/java/com/moczul/ok2curl/CurlInterceptor.java index 7340748..97827e3 100644 --- a/ok2curl/src/main/java/com/moczul/ok2curl/CurlInterceptor.java +++ b/ok2curl/src/main/java/com/moczul/ok2curl/CurlInterceptor.java @@ -19,6 +19,7 @@ public class CurlInterceptor implements Interceptor { private final Loggable logger; private final long limit; private final List headerModifiers = new ArrayList<>(); + private final Options options; /** * Interceptor responsible for printing curl logs @@ -28,7 +29,19 @@ public class CurlInterceptor implements Interceptor { * @param logger output of logging */ public CurlInterceptor(Loggable logger) { - this(logger, DEFAULT_LIMIT, Collections.emptyList()); + this(logger, DEFAULT_LIMIT, Collections.emptyList(), Options.EMPTY); + } + + /** + * Interceptor responsible for printing curl logs + * + * Logs are pushed to stdout with 1MB limit + * + * @param logger output of logging + * @param options list of curl options + */ + public CurlInterceptor(Loggable logger, Options options) { + this(logger, DEFAULT_LIMIT, Collections.emptyList(), options); } /** @@ -38,7 +51,7 @@ public CurlInterceptor(Loggable logger) { * @param headerModifiers list of header modifiers */ public CurlInterceptor(Loggable logger, List headerModifiers) { - this(logger, DEFAULT_LIMIT, headerModifiers); + this(logger, DEFAULT_LIMIT, headerModifiers, Options.EMPTY); } /** @@ -48,7 +61,7 @@ public CurlInterceptor(Loggable logger, List headerModifiers) { * @param limit limit maximal bytes logged, if negative - non limited */ public CurlInterceptor(Loggable logger, long limit) { - this(logger, limit, Collections.emptyList()); + this(logger, limit, Collections.emptyList(), Options.EMPTY); } /** @@ -56,11 +69,13 @@ public CurlInterceptor(Loggable logger, long limit) { * @param logger output of logging * @param limit limit maximal bytes logged, if negative - non limited * @param headerModifiers list of header modifiers + * @param options list of curl options */ - public CurlInterceptor(Loggable logger, long limit, List headerModifiers) { + public CurlInterceptor(Loggable logger, long limit, List headerModifiers, Options options) { this.logger = logger; this.limit = limit; this.headerModifiers.addAll(headerModifiers); + this.options = options; } @Override @@ -68,7 +83,7 @@ public Response intercept(Chain chain) throws IOException { final Request request = chain.request(); final Request copy = request.newBuilder().build(); - final String curl = new CurlBuilder(copy, limit, headerModifiers).build(); + final String curl = new CurlBuilder(copy, limit, headerModifiers, options).build(); logger.log(curl); diff --git a/ok2curl/src/main/java/com/moczul/ok2curl/Options.java b/ok2curl/src/main/java/com/moczul/ok2curl/Options.java new file mode 100644 index 0000000..3ebce5b --- /dev/null +++ b/ok2curl/src/main/java/com/moczul/ok2curl/Options.java @@ -0,0 +1,68 @@ +package com.moczul.ok2curl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +public class Options { + + public static final Options EMPTY = new Options(Collections.emptyList()); + + private final List options; + + public static Builder builder() { + return new Builder(); + } + + private Options(Collection options) { + this.options = new ArrayList<>(options); + } + + public List list() { + return options; + } + + public static class Builder { + + private final Set options = new HashSet<>(); + + public Builder insecure() { + options.add("--insecure"); + return this; + } + + public Builder maxTime(int seconds) { + options.add(String.format(Locale.getDefault(), "--max-time %d", seconds)); + return this; + } + + public Builder connectTimeout(int seconds) { + options.add(String.format(Locale.getDefault(), "--connect-timeout %d", seconds)); + return this; + } + + public Builder retry(int num) { + options.add(String.format(Locale.getDefault(), "--retry %d", num)); + return this; + } + + public Builder compressed() { + options.add("--compressed"); + return this; + } + + public Builder location() { + options.add("--location"); + return this; + } + + public Options build() { + return new Options(options); + } + } + +} diff --git a/ok2curl/src/test/java/com/moczul/ok2curl/OptionsTest.java b/ok2curl/src/test/java/com/moczul/ok2curl/OptionsTest.java new file mode 100644 index 0000000..74e8b0c --- /dev/null +++ b/ok2curl/src/test/java/com/moczul/ok2curl/OptionsTest.java @@ -0,0 +1,58 @@ +package com.moczul.ok2curl; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +public class OptionsTest { + + @Test + public void defaultBuilderShouldReturnEmptyOptions() { + final Options options = Options.builder().build(); + + assertThat(options.list().size(), is(0)); + } + + @Test + public void shouldCorrectlyHandleOptionsParameters() { + final Options options = Options + .builder() + .maxTime(120) + .connectTimeout(60) + .retry(3) + .build(); + + assertThat(options.list().size(), is(3)); + assertThat(options.list(), hasItem("--max-time 120")); + assertThat(options.list(), hasItem("--connect-timeout 60")); + assertThat(options.list(), hasItem("--retry 3")); + } + + @Test + public void shouldReturnCorrectListOfParameters() { + final Options options = Options.builder() + .insecure() + .compressed() + .location() + .build(); + + assertThat(options.list().size(), is(3)); + assertThat(options.list(), hasItem("--insecure")); + assertThat(options.list(), hasItem("--compressed")); + assertThat(options.list(), hasItem("--location")); + } + + @Test + public void shouldIgnoreDuplicatedParameteres() { + final Options options = Options.builder() + .insecure() + .insecure() + .insecure() + .build(); + + assertThat(options.list().size(), is(1)); + assertThat(options.list(), hasItem("--insecure")); + } +} \ No newline at end of file diff --git a/ok2curl/src/test/java/com/moczul/ok2curl/util/HeaderModifierTest.java b/ok2curl/src/test/java/com/moczul/ok2curl/util/HeaderModifierTest.java index 08af7f4..98a9740 100644 --- a/ok2curl/src/test/java/com/moczul/ok2curl/util/HeaderModifierTest.java +++ b/ok2curl/src/test/java/com/moczul/ok2curl/util/HeaderModifierTest.java @@ -2,6 +2,7 @@ import com.moczul.ok2curl.CurlBuilder; import com.moczul.ok2curl.Header; +import com.moczul.ok2curl.Options; import com.moczul.ok2curl.modifier.HeaderModifier; import org.junit.Test; @@ -42,33 +43,33 @@ public Header modify(Header header) { }; @Test - public void curlCommand_shouldContains_modifiedHeader() throws Exception { + public void curlCommand_shouldContains_modifiedHeader() { final Request request = new Request.Builder() .url("http://example.com/") .header("Cookie", "FIRST=foo") .build(); final List modifiers = Collections.singletonList(cookieHeaderModifier); - final String command = new CurlBuilder(request, -1L, modifiers).build(); + final String command = new CurlBuilder(request, -1L, modifiers, Options.EMPTY).build(); assertEquals("curl -X GET -H \"Cookie:modifiedCookieValue\" http://example.com/", command); } @Test - public void curlCommand_shouldNotBeModified_ifDoesNotContainMatchingHeader() throws Exception { + public void curlCommand_shouldNotBeModified_ifDoesNotContainMatchingHeader() { final Request request = new Request.Builder() .url("http://example.com/") .header("Accept", "application/json") .build(); final List modifiers = Collections.singletonList(cookieHeaderModifier); - final String command = new CurlBuilder(request, -1L, modifiers).build(); + final String command = new CurlBuilder(request, -1L, modifiers, Options.EMPTY).build(); assertEquals("curl -X GET -H \"Accept:application/json\" http://example.com/", command); } @Test - public void curlCommand_shouldNotContainsAnyHeaders_forNullHeaderModifier() throws Exception { + public void curlCommand_shouldNotContainsAnyHeaders_forNullHeaderModifier() { final Request request = new Request.Builder() .url("http://example.com/") .header("Cookie", "FIRST=foo") @@ -76,7 +77,7 @@ public void curlCommand_shouldNotContainsAnyHeaders_forNullHeaderModifier() thro .build(); final List modifiers = Collections.singletonList(nullHeaderModifier); - final String command = new CurlBuilder(request, -1L, modifiers).build(); + final String command = new CurlBuilder(request, -1L, modifiers, Options.EMPTY).build(); assertEquals(command, "curl -X GET http://example.com/", command); } diff --git a/sample/src/main/java/com/moczul/sample/MainActivity.java b/sample/src/main/java/com/moczul/sample/MainActivity.java index aa46491..3b7e8ac 100644 --- a/sample/src/main/java/com/moczul/sample/MainActivity.java +++ b/sample/src/main/java/com/moczul/sample/MainActivity.java @@ -7,6 +7,7 @@ import android.widget.TextView; import com.moczul.ok2curl.CurlBuilder; +import com.moczul.ok2curl.Options; import com.moczul.ok2curl.modifier.HeaderModifier; import com.moczul.sample.modifier.Base64Decoder; import com.moczul.sample.modifier.BasicAuthorizationHeaderModifier; @@ -23,7 +24,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - curlLog = (TextView) findViewById(R.id.curl_log); + curlLog = findViewById(R.id.curl_log); findViewById(R.id.get_request).setOnClickListener(this); findViewById(R.id.post_request).setOnClickListener(this); @@ -41,7 +42,7 @@ private void displayCurlLog(String type) { final BasicAuthorizationHeaderModifier modifier = new BasicAuthorizationHeaderModifier(new Base64Decoder()); final List modifiers = Collections.singletonList(modifier); - final String curl = new CurlBuilder(RequestFactory.getRequest(type), -1L, modifiers).build(); + final String curl = new CurlBuilder(RequestFactory.getRequest(type), -1L, modifiers, Options.EMPTY).build(); curlLog.setText(curl); } From 5fab164c4008501a02a9f1e45afe3909068a607e Mon Sep 17 00:00:00 2001 From: Michal Moczulski Date: Sun, 21 Jan 2018 20:40:33 +0100 Subject: [PATCH 2/4] Tests options in CurlBuilderTest --- .../com/moczul/ok2curl/CurlBuilderTest.java | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/ok2curl/src/test/java/com/moczul/ok2curl/CurlBuilderTest.java b/ok2curl/src/test/java/com/moczul/ok2curl/CurlBuilderTest.java index a12c847..0e3a98d 100644 --- a/ok2curl/src/test/java/com/moczul/ok2curl/CurlBuilderTest.java +++ b/ok2curl/src/test/java/com/moczul/ok2curl/CurlBuilderTest.java @@ -1,9 +1,10 @@ package com.moczul.ok2curl; +import com.moczul.ok2curl.modifier.HeaderModifier; + import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import java.util.Collections; import java.util.concurrent.TimeUnit; import okhttp3.CacheControl; @@ -16,26 +17,28 @@ public class CurlBuilderTest { @Test - public void getRequest_hasCorrectCommand() { + public void getRequestHasCorrectCommand() { final Request request = new Request.Builder().url("http://example.com/").build(); + final String command = new CurlBuilder(request).build(); assertEquals("curl -X GET http://example.com/", command); } @Test - public void getRequest_hasCorrectHeader() { + public void getRequestHasCorrectHeader() { final Request request = new Request.Builder() .url("http://example.com/") .header("Accept", "application/json") .build(); + final String command = new CurlBuilder(request).build(); assertEquals("curl -X GET -H \"Accept:application/json\" http://example.com/", command); } @Test - public void getRequest_hasCorrectCacheHeader() { + public void getRequestHasCorrectCacheHeader() { final CacheControl cache = new CacheControl.Builder() .maxAge(1, TimeUnit.DAYS) .onlyIfCached() @@ -52,8 +55,9 @@ public void getRequest_hasCorrectCacheHeader() { } @Test - public void postRequest_hasCorrectPostData() { + public void postRequestHasCorrectPostData() { final Request request = new Request.Builder().url("http://example.com/").post(body()).build(); + final String command = new CurlBuilder(request).build(); final String expected = "curl -X POST -H \"Content-Type:application/x-www-form-urlencoded\" -d 'key1=value1' http://example.com/"; @@ -61,9 +65,10 @@ public void postRequest_hasCorrectPostData() { } @Test - public void postRequest_bodyWithNullMediaType() { + public void postRequestBodyWithNullMediaType() { final RequestBody body = RequestBody.create(null, "StringBody"); final Request request = new Request.Builder().url("http://example.com/").post(body).build(); + final String command = new CurlBuilder(request).build(); final String expected = "curl -X POST -d 'StringBody' http://example.com/"; @@ -71,7 +76,7 @@ public void postRequest_bodyWithNullMediaType() { } @Test - public void multipleHeadersWithTheSameName_shouldBeAddedToCurlCommand() { + public void multipleHeadersWithTheSameNameShouldBeAddedToCurlCommand() { final Request request = new Request.Builder() .url("http://example.com/") .addHeader("Cookie", "FIRST=foo") @@ -83,6 +88,26 @@ public void multipleHeadersWithTheSameName_shouldBeAddedToCurlCommand() { assertEquals("curl -X GET -H \"Cookie:FIRST=foo\" -H \"Cookie:SECOND=bar\" http://example.com/", command); } + @Test + public void getRequestContainsInsecureOption() { + final Request request = new Request.Builder().url("http://example.com/").build(); + final Options options = Options.builder().insecure().build(); + + final String command = new CurlBuilder(request, 1024, Collections.emptyList(), options).build(); + + assertEquals("curl --insecure -X GET http://example.com/", command); + } + + @Test + public void getRequestContainsConnectTimeoutOptions() { + final Request request = new Request.Builder().url("http://example.com/").build(); + final Options options = Options.builder().connectTimeout(120).build(); + + final String command = new CurlBuilder(request, 1024, Collections.emptyList(), options).build(); + + assertEquals("curl --connect-timeout 120 -X GET http://example.com/", command); + } + private RequestBody body() { return new FormBody.Builder().add("key1", "value1").build(); } From 4834e5c8f4bc9a4a36a753af7d81754bca505e8a Mon Sep 17 00:00:00 2001 From: Michal Moczulski Date: Sun, 21 Jan 2018 20:42:16 +0100 Subject: [PATCH 3/4] Bump lib version to 0.4.0 --- ok2curl/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ok2curl/build.gradle b/ok2curl/build.gradle index 15a2f49..4037a37 100644 --- a/ok2curl/build.gradle +++ b/ok2curl/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'java' apply plugin: 'maven' group='com.github.mrmike' -version='0.3.2' +version='0.4.0' targetCompatibility = '1.7' sourceCompatibility = '1.7' From 577e208e77538fa69112ea28c0307d99c48358e2 Mon Sep 17 00:00:00 2001 From: Michal Moczulski Date: Sun, 21 Jan 2018 20:47:49 +0100 Subject: [PATCH 4/4] Update README --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9697831..dbe48be 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ dependencies { // snapshot version compile 'com.github.mrmike:Ok2Curl:master-SNAPSHOT' // or use specific version - compile 'com.github.mrmike:Ok2Curl:0.3.1' + compile 'com.github.mrmike:Ok2Curl:0.4.0' } ``` @@ -57,9 +57,34 @@ final List modifiers = Collections.singletonList final CurlInterceptor curlInterceptor = new CurlInterceptor(new AndroidLogger(), modifiers); ``` +## Options +Ok2Curl supports basic Curl options. In order to use options use the following code: +``` +final Options options = Options.builder() + .insecure() + .connectTimeout(120) + .retry(5) + .build(); + +final CurlInterceptor interceptor = new CurlInterceptor(logger, options); +``` +Since now every Curl command will start with `curl --insecure --connect-timeout 120 --retry 5...` + +### Supported options +* --insecure +* --max-time seconds +* --connect-timeout seconds +* --retry num +* --compressed +* --location + +If would like to support any new options please feel free to open PR. Full list of curl options is +available [here](https://curl.haxx.se/docs/manpage.html). + + ## License - Copyright 2015 Michał Moczulski + Copyright 2018 Michał Moczulski Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.