diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..29c65d9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: CI + +on: + push: + branches: [ master, main ] + pull_request: + branches: [ master, main ] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Build and Test + run: mvn clean test post-integration-test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..776b6aa --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,37 @@ +name: Release + +on: + push: + tags: [ 'v*' ] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + server-id: maven-central-staging + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }} + gpg-passphrase: MAVEN_GPG_PASSPHRASE + + - name: Cache Maven packages + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- + + - name: Deploy to Maven Central + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: mvn deploy -DskipTests=true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 263ca93..0000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -sudo: required -dist: trusty -language: java -jdk: - - openjdk8 -addons: - sonarcloud: - organization: yassine-github - token: - secure: PYT5/IbiqFd877vdi+CYTx7srXr5ACvAgBSL4rxPqwVSQUdGIZxVTj8JcZp7Cl2WiDj9zDlTHSDaJDt5ZpXnmN5quJBizuCZDVArm3LoRADjxhOd9N8rQEYEE1TZOHlu1+g1i/abOL+av9Spn7lWk1LvuH5BW3b0GiAdqJFevfnJsUYDh4iYHiMYjTIP5dO/cZUnQzgFgZS6YkMA28cgQIy/F03z6tO9oM6kcJ/DGBnqvdGAT2ZxtWhFaaNwJazlxSePCwnOok+v3vgACzGospTJLQ4AdGklYIK+ljGpz7AbiRs7yhvzsib6i5Wr0IEmZmLiyIgjExPdnV+rXAndgig/0bnhv1YzyEf/hCzMczpHvNa0HDAGCxkTIsw76XlumwPMGURdlypWEoWrz/9cwiPMnQ0XcAOTN56msA5nBbNwnJ9KDKIVWKWg447OhbImlTr+qxHI/L+8e1dFxyA1iBg7/wtU/27V2QRABvhdlVGNn1khdkIKhsueYHbBjloUTILHBFKTtJdZdD2z/Vf9cu51EQDwv5IPfkkz/UER8pw4AVKgFi6v57M3unqE5C6g8dZr5CELAqy3tGjf6v9HaTF3AdGEkyIJuxiiO8LM20MJm+IreR/pIv8SVeT7f747hbPCQ+mMe5rSE4KVtSI88OeUcI193pdd5PBg0jU262I= -jobs: - include: - - stage: test - script: - - mvn clean test post-integration-test sonar:sonar - - stage: release - script: - - openssl enc -aes-256-cbc -d -in ./.travis/ipdata-java.crypted.gpg.key -out ./.travis/ipdata.out.key -base64 -K $GPG_AES_KEY -iv $GPG_AES_KEY_IV -S $GPG_AES_KEY_SALT - - echo $GPG_PASSPHRASE | gpg --import --batch --yes --passphrase-fd 0 ./.travis/ipdata.out.key - - mvn package verify -Prelease -DskipTests=true -Dgpg.keyname=$GPG_KEY_NAME -Dgpg.passphrase=$GPG_PASSPHRASE -stages: - - test - - name: release - if: branch = releases -notifications: - email: false diff --git a/.travis/ipdata-java.crypted.gpg.key b/.travis/ipdata-java.crypted.gpg.key deleted file mode 100644 index 3d0f7e7..0000000 --- a/.travis/ipdata-java.crypted.gpg.key +++ /dev/null @@ -1,104 +0,0 @@ -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 -U+Rp4aeEC3Y4YxX8WAppkQ== diff --git a/README.md b/README.md index df98fbc..619f88d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,5 @@ # ipdata-java-client -![Build Status](https://www.travis-ci.org/yassine/ipdata-java-client.svg?branch=master) -[![Coverage Status](https://sonarcloud.io/api/project_badges/measure?metric=coverage&project=yassine_ipdata-java-client)](https://sonarcloud.io/dashboard/index/yassine_ipdata-java-client) -[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?metric=alert_status&project=yassine_ipdata-java-client)](https://sonarcloud.io/dashboard/index/yassine_ipdata-java-client) -[![Maintainability](https://sonarcloud.io/api/project_badges/measure?metric=sqale_rating&project=yassine_ipdata-java-client)](https://sonarcloud.io/dashboard/index/yassine_ipdata-java-client) -[![Reliability](https://sonarcloud.io/api/project_badges/measure?metric=reliability_rating&project=yassine_ipdata-java-client)](https://sonarcloud.io/dashboard/index/yassine_ipdata-java-client) +![Build Status](https://github.com/ipdata/java/actions/workflows/ci.yml/badge.svg) An 100% compliant [ipdata.co](https://ipdata.co) API java client. diff --git a/pom.xml b/pom.xml index 05a571d..469a84e 100644 --- a/pom.xml +++ b/pom.xml @@ -39,17 +39,7 @@ 11 11 UTF-8 - ${project.build.directory}/site/code-coverage/jacoco.xml - https://sonarcloud.io - https://github.com/ipdata/java - https://github.com/ipdata/java - https://github.com/ipdata/java - yassine-github - yassine_ipdata-java-client - ipdata-java-client - ${project.version} 0.8.14 - 3.11.0.3922 3.5.5 11.10 @@ -68,6 +58,7 @@ io.github.openfeign feign-httpclient ${version.client.feign} + test com.google.guava @@ -81,13 +72,15 @@ org.slf4j - slf4j-log4j12 + slf4j-simple 1.7.36 + test org.projectlombok lombok 1.18.38 + provided org.hamcrest @@ -168,12 +161,7 @@ ${surefireArgLine} - - org.codehaus.mojo - sonar-maven-plugin - ${version.build.sonar} - - + maven-source-plugin 3.3.1 diff --git a/src/main/java/io/ipdata/client/model/Blocklist.java b/src/main/java/io/ipdata/client/model/Blocklist.java new file mode 100644 index 0000000..5ca4201 --- /dev/null +++ b/src/main/java/io/ipdata/client/model/Blocklist.java @@ -0,0 +1,11 @@ +package io.ipdata.client.model; + +import lombok.Getter; +import lombok.ToString; + +@Getter @ToString +public class Blocklist { + private String name; + private String site; + private String type; +} diff --git a/src/main/java/io/ipdata/client/model/IpdataModel.java b/src/main/java/io/ipdata/client/model/IpdataModel.java index 1bef8d9..7d8cf62 100644 --- a/src/main/java/io/ipdata/client/model/IpdataModel.java +++ b/src/main/java/io/ipdata/client/model/IpdataModel.java @@ -1,15 +1,12 @@ package io.ipdata.client.model; import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.AccessLevel; import lombok.Getter; -import lombok.Setter; import lombok.ToString; import lombok.experimental.Accessors; import java.util.List; -@Setter(AccessLevel.PACKAGE) @ToString @Getter @Accessors(fluent = true) diff --git a/src/main/java/io/ipdata/client/model/Scores.java b/src/main/java/io/ipdata/client/model/Scores.java new file mode 100644 index 0000000..5049a83 --- /dev/null +++ b/src/main/java/io/ipdata/client/model/Scores.java @@ -0,0 +1,17 @@ +package io.ipdata.client.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.ToString; + +@Getter @ToString +public class Scores { + @JsonProperty("vpn_score") + private int vpnScore; + @JsonProperty("proxy_score") + private int proxyScore; + @JsonProperty("threat_score") + private int threatScore; + @JsonProperty("trust_score") + private int trustScore; +} diff --git a/src/main/java/io/ipdata/client/model/ThreatModel.java b/src/main/java/io/ipdata/client/model/ThreatModel.java index 2d61f12..8b96baa 100644 --- a/src/main/java/io/ipdata/client/model/ThreatModel.java +++ b/src/main/java/io/ipdata/client/model/ThreatModel.java @@ -1,6 +1,7 @@ package io.ipdata.client.model; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; import lombok.Getter; import lombok.ToString; @@ -8,6 +9,8 @@ public class ThreatModel { @JsonProperty("is_tor") private boolean tor; + @JsonProperty("is_vpn") + private boolean vpn; @JsonProperty("is_proxy") private boolean proxy; @JsonProperty("is_anonymous") @@ -24,4 +27,6 @@ public class ThreatModel { private boolean icloudRelay; @JsonProperty("is_datacenter") private boolean datacenter; + private List blocklists; + private Scores scores; } diff --git a/src/main/java/io/ipdata/client/service/ApiKeyRequestInterceptor.java b/src/main/java/io/ipdata/client/service/ApiKeyRequestInterceptor.java index bfacdd7..a361660 100644 --- a/src/main/java/io/ipdata/client/service/ApiKeyRequestInterceptor.java +++ b/src/main/java/io/ipdata/client/service/ApiKeyRequestInterceptor.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; @RequiredArgsConstructor @Slf4j @@ -22,7 +23,7 @@ class ApiKeyRequestInterceptor implements RequestInterceptor { String version; try { version = CharStreams.toString(new InputStreamReader(ApiKeyRequestInterceptor.class - .getResourceAsStream("/io/ipdata/client/VERSION"))).replaceAll("\\n", ""); + .getResourceAsStream("/io/ipdata/client/VERSION"), StandardCharsets.UTF_8)).replaceAll("\\n", ""); version = String.format("io.ipdata.client.java.%s", version); } catch (Exception e) { log.error(e.getMessage(), e); diff --git a/src/main/java/io/ipdata/client/service/CachingInternalClient.java b/src/main/java/io/ipdata/client/service/CachingInternalClient.java index 30aa99f..08de093 100644 --- a/src/main/java/io/ipdata/client/service/CachingInternalClient.java +++ b/src/main/java/io/ipdata/client/service/CachingInternalClient.java @@ -29,12 +29,20 @@ class CachingInternalClient implements IpdataInternalClient, IpdataInternalSingl private final LoadingCache currencyCache; private final LoadingCache threatCache; + private static IpdataException unwrap(ExecutionException e) throws IpdataException { + Throwable cause = e.getCause(); + if (cause instanceof IpdataException) { + throw (IpdataException) cause; + } + throw new IpdataException(cause != null ? cause.getMessage() : e.getMessage(), cause != null ? cause : e); + } + @Override public IpdataModel getFields(String ip, String fields) throws IpdataException { try { return fieldsCache.get(HashPair.of(ip, fields)); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } @@ -43,7 +51,7 @@ public AsnModel asn(String ip) throws IpdataException { try { return asnCache.get(ip); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } @@ -52,7 +60,7 @@ public TimeZone timeZone(String ip) throws IpdataException { try { return tzCache.get(ip); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } @@ -61,7 +69,7 @@ public Currency currency(String ip) throws IpdataException { try { return currencyCache.get(ip); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } @@ -70,7 +78,7 @@ public ThreatModel threat(String ip) throws IpdataException { try { return threatCache.get(ip); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } @@ -79,7 +87,7 @@ public IpdataModel ipdata(String ip) throws IpdataException { try { return ipdataCache.get(ip); } catch (ExecutionException e) { - throw new IpdataException(e.getMessage(), e); + throw unwrap(e); } } diff --git a/src/main/java/io/ipdata/client/service/IpdataService.java b/src/main/java/io/ipdata/client/service/IpdataService.java index dce4ea3..d83d522 100644 --- a/src/main/java/io/ipdata/client/service/IpdataService.java +++ b/src/main/java/io/ipdata/client/service/IpdataService.java @@ -5,13 +5,48 @@ import java.util.List; +/** + * Primary interface for accessing the ipdata.co API. + *

+ * Provides methods for looking up geolocation, threat intelligence, and other + * metadata for IP addresses. Supports single IP lookups, bulk lookups, and + * selective field retrieval. + *

+ * Also exposes single-field accessors (e.g. {@code getCountryName}, {@code getCity}) + * inherited from {@link IpdataInternalSingleFieldClient}. + * + * @see io.ipdata.client.Ipdata#builder() + */ public interface IpdataService extends IpdataInternalSingleFieldClient { + /** + * Retrieves the full IP data model for the given IP address. + * + * @param ip an IPv4 or IPv6 address + * @return the full geolocation and metadata for the IP + * @throws IpdataException if the API call fails + */ IpdataModel ipdata(String ip) throws IpdataException; + /** + * Retrieves IP data for multiple IP addresses in a single request. + * + * @param ips list of IPv4 or IPv6 addresses + * @return a list of IP data models, one per input address + * @throws IpdataException if the API call fails + */ List bulk(List ips) throws IpdataException; - IpdataModel[] bulkAsArray(List ips) throws IpdataException; - + /** + * Retrieves only the specified fields for the given IP address. + *

+ * Fields are sorted before querying to maximize cache hit rates when caching is enabled. + * + * @param ip an IPv4 or IPv6 address + * @param fields one or more fields to retrieve (e.g. {@code IpdataField.ASN}, {@code IpdataField.CURRENCY}) + * @return a partial IP data model containing only the requested fields + * @throws IpdataException if the API call fails + * @throws IllegalArgumentException if no fields are specified + */ IpdataModel getFields(String ip, IpdataField... fields) throws IpdataException; } diff --git a/src/main/java/io/ipdata/client/service/IpdataServiceBuilder.java b/src/main/java/io/ipdata/client/service/IpdataServiceBuilder.java index af68fda..f294cc2 100644 --- a/src/main/java/io/ipdata/client/service/IpdataServiceBuilder.java +++ b/src/main/java/io/ipdata/client/service/IpdataServiceBuilder.java @@ -9,7 +9,6 @@ import com.google.common.cache.CacheLoader; import feign.Client; import feign.Feign; -import feign.httpclient.ApacheHttpClient; import feign.jackson.JacksonDecoder; import feign.jackson.JacksonEncoder; import io.ipdata.client.model.*; @@ -19,7 +18,7 @@ import java.net.URL; -import static com.fasterxml.jackson.databind.PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES; +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SNAKE_CASE; @RequiredArgsConstructor(staticName = "of") public class IpdataServiceBuilder { @@ -32,7 +31,7 @@ public class IpdataServiceBuilder { public IpdataService build() { final ObjectMapper mapper = new ObjectMapper(); - mapper.setPropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); + mapper.setPropertyNamingStrategy(SNAKE_CASE); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); @@ -42,7 +41,7 @@ public IpdataService build() { final ApiErrorDecoder apiErrorDecoder = new ApiErrorDecoder(mapper, customLogger); final IpdataInternalClient client = Feign.builder() - .client(httpClient == null ? new ApacheHttpClient() : httpClient) + .client(new Ipv6SafeClient(httpClient == null ? new Client.Default(null, null) : httpClient)) .decoder(new JacksonDecoder(mapper)) .encoder(new JacksonEncoder(mapper)) .requestInterceptor(keyRequestInterceptor) @@ -50,7 +49,7 @@ public IpdataService build() { .target(IpdataInternalClient.class, url.toString()); final IpdataInternalSingleFieldClient singleFieldClient = Feign.builder() - .client(httpClient == null ? new ApacheHttpClient() : httpClient) + .client(new Ipv6SafeClient(httpClient == null ? new Client.Default(null, null) : httpClient)) .decoder(new FieldDecoder(mapper)) .encoder(new JacksonEncoder(mapper)) .requestInterceptor(keyRequestInterceptor) diff --git a/src/main/java/io/ipdata/client/service/IpdataServiceSupport.java b/src/main/java/io/ipdata/client/service/IpdataServiceSupport.java index 7f7324e..7531ba8 100644 --- a/src/main/java/io/ipdata/client/service/IpdataServiceSupport.java +++ b/src/main/java/io/ipdata/client/service/IpdataServiceSupport.java @@ -30,15 +30,10 @@ private IpdataInternalSingleFieldClient getApi() { return singleFieldClient; } - @Override - public IpdataModel[] bulkAsArray(List ips) throws IpdataException { - return bulk(ips).toArray(new IpdataModel[0]); - } - @Override public IpdataModel getFields(String ip, IpdataField... fields) throws IpdataException { if (fields.length == 0) { - return null; + throw new IllegalArgumentException("At least one field must be specified"); } //sorting here to improve the likelihood of a cache hit, otherwise a permutation of the same //array would result into a different cache key, and thus a cache miss diff --git a/src/main/java/io/ipdata/client/service/Ipv6SafeClient.java b/src/main/java/io/ipdata/client/service/Ipv6SafeClient.java new file mode 100644 index 0000000..f8f6f38 --- /dev/null +++ b/src/main/java/io/ipdata/client/service/Ipv6SafeClient.java @@ -0,0 +1,44 @@ +package io.ipdata.client.service; + +import feign.Client; +import feign.Request; +import feign.Response; + +import java.io.IOException; + +/** + * A Feign Client wrapper that prevents percent-encoding of colons in the request path. + *

+ * Feign's template engine may percent-encode colons in path parameters (e.g., IPv6 addresses), + * converting {@code 2001:4860:4860::8888} to {@code 2001%3A4860%3A4860%3A%3A8888}. + * Colons are valid in URI path segments per RFC 3986 section 3.3, so this wrapper + * decodes them before forwarding to the underlying HTTP client. + * + * @see Issue #10 + */ +class Ipv6SafeClient implements Client { + + private final Client delegate; + + Ipv6SafeClient(Client delegate) { + this.delegate = delegate; + } + + @Override + public Response execute(Request request, Request.Options options) throws IOException { + String url = request.url(); + int queryIndex = url.indexOf('?'); + String path = queryIndex >= 0 ? url.substring(0, queryIndex) : url; + + if (path.contains("%3A") || path.contains("%3a")) { + String fixedPath = path.replace("%3A", ":").replace("%3a", ":"); + String query = queryIndex >= 0 ? url.substring(queryIndex) : ""; + String fixedUrl = fixedPath + query; + request = Request.create( + request.httpMethod(), fixedUrl, request.headers(), + request.body(), request.charset() + ); + } + return delegate.execute(request, options); + } +} diff --git a/src/test/java/io/ipdata/client/EdgeCaseTest.java b/src/test/java/io/ipdata/client/EdgeCaseTest.java new file mode 100644 index 0000000..1874198 --- /dev/null +++ b/src/test/java/io/ipdata/client/EdgeCaseTest.java @@ -0,0 +1,73 @@ +package io.ipdata.client; + +import io.ipdata.client.error.IpdataException; +import io.ipdata.client.error.RemoteIpdataException; +import io.ipdata.client.model.IpdataModel; +import io.ipdata.client.service.IpdataService; +import lombok.SneakyThrows; +import org.junit.Assert; +import org.junit.Test; + +import static io.ipdata.client.service.IpdataField.ASN; +import static io.ipdata.client.service.IpdataField.CURRENCY; + +public class EdgeCaseTest { + + private static final TestContext TEST_CONTEXT = new TestContext(MockIpdataServer.API_KEY, MockIpdataServer.getInstance().getUrl()); + + @Test(expected = IllegalArgumentException.class) + @SneakyThrows + public void testGetFieldsWithNoFieldsThrows() { + IpdataService service = TEST_CONTEXT.ipdataService(); + service.getFields("8.8.8.8"); + } + + @Test(expected = IllegalArgumentException.class) + @SneakyThrows + public void testGetFieldsWithNoFieldsThrowsCaching() { + IpdataService service = TEST_CONTEXT.cachingIpdataService(); + service.getFields("8.8.8.8"); + } + + @Test + @SneakyThrows + public void testInvalidKeyReturnsRemoteException() { + IpdataService service = Ipdata.builder() + .url(TEST_CONTEXT.url()) + .key("INVALID_KEY") + .noCache() + .get(); + try { + service.ipdata("8.8.8.8"); + Assert.fail("Expected RemoteIpdataException"); + } catch (RemoteIpdataException e) { + Assert.assertEquals(401, e.getStatus()); + Assert.assertNotNull(e.getMessage()); + } + } + + @Test + @SneakyThrows + public void testCachedInvalidKeyUnwrapsException() { + IpdataService service = Ipdata.builder() + .url(TEST_CONTEXT.url()) + .key("INVALID_KEY") + .withDefaultCache() + .get(); + try { + service.ipdata("8.8.8.8"); + Assert.fail("Expected RemoteIpdataException"); + } catch (RemoteIpdataException e) { + Assert.assertEquals(401, e.getStatus()); + } + } + + @Test + @SneakyThrows + public void testGetFieldsReturnsSelectedFields() { + IpdataService service = TEST_CONTEXT.ipdataService(); + IpdataModel model = service.getFields("8.8.8.8", ASN, CURRENCY); + Assert.assertNotNull(model.asn()); + Assert.assertNotNull(model.currency()); + } +} diff --git a/src/test/java/io/ipdata/client/FullModelTest.java b/src/test/java/io/ipdata/client/FullModelTest.java index 99bfa72..55424e8 100644 --- a/src/test/java/io/ipdata/client/FullModelTest.java +++ b/src/test/java/io/ipdata/client/FullModelTest.java @@ -1,18 +1,15 @@ package io.ipdata.client; -import feign.httpclient.ApacheHttpClient; import io.ipdata.client.error.IpdataException; +import io.ipdata.client.error.RemoteIpdataException; import io.ipdata.client.model.IpdataModel; import io.ipdata.client.service.IpdataService; import lombok.SneakyThrows; -import org.apache.http.impl.client.HttpClientBuilder; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import java.util.concurrent.TimeUnit; - @RunWith(Parameterized.class) public class FullModelTest { @@ -44,21 +41,24 @@ public void testFullResponse() { public void testSingleFields() { IpdataService ipdataService = fixture.service(); String field = ipdataService.getCountryName(fixture.target()); - String expected = TEST_CONTEXT.get("/8.8.8.8/country_name", null); - Assert.assertEquals(field, expected); + String expected = TEST_CONTEXT.get("/" + fixture.target() + "/country_name", null); + Assert.assertEquals(expected, field); } @SneakyThrows - @Test(expected = IpdataException.class) + @Test public void testError() { IpdataService serviceWithInvalidKey = Ipdata.builder().url(TEST_CONTEXT.url()) .key("THIS_IS_AN_INVALID_KEY") - .withDefaultCache() - .feignClient(new ApacheHttpClient(HttpClientBuilder.create() - .setConnectionTimeToLive(10, TimeUnit.SECONDS) - .build())).get(); - serviceWithInvalidKey.ipdata(fixture.target()); + .noCache() + .get(); + try { + serviceWithInvalidKey.ipdata(fixture.target()); + Assert.fail("Expected RemoteIpdataException"); + } catch (RemoteIpdataException e) { + Assert.assertEquals(401, e.getStatus()); + } } @Parameterized.Parameters diff --git a/src/test/java/io/ipdata/client/Ipv6EncodingTest.java b/src/test/java/io/ipdata/client/Ipv6EncodingTest.java new file mode 100644 index 0000000..fddbac7 --- /dev/null +++ b/src/test/java/io/ipdata/client/Ipv6EncodingTest.java @@ -0,0 +1,36 @@ +package io.ipdata.client; + +import io.ipdata.client.model.IpdataModel; +import io.ipdata.client.service.IpdataService; +import lombok.SneakyThrows; +import org.junit.Assert; +import org.junit.Test; + +/** + * Regression test for https://github.com/ipdata/java/issues/10 + * Verifies that IPv6 colons are not percent-encoded (%3A) in HTTP requests. + */ +public class Ipv6EncodingTest { + + private static final MockIpdataServer MOCK = MockIpdataServer.getInstance(); + private static final TestContext TEST_CONTEXT = new TestContext(MockIpdataServer.API_KEY, MOCK.getUrl()); + + @Test + @SneakyThrows + public void testIpv6ColonsAreNotEncoded() { + String ipv6 = "2001:4860:4860::8888"; + IpdataService service = TEST_CONTEXT.ipdataService(); + IpdataModel model = service.ipdata(ipv6); + Assert.assertNotNull(model); + + String rawPath = MOCK.getLastRawPath(); + Assert.assertFalse( + "IPv6 colons should not be percent-encoded in the request path, but got: " + rawPath, + rawPath.contains("%3A") + ); + Assert.assertTrue( + "Request path should contain the IPv6 address with literal colons", + rawPath.contains(ipv6) + ); + } +} diff --git a/src/test/java/io/ipdata/client/MockIpdataServer.java b/src/test/java/io/ipdata/client/MockIpdataServer.java index 6f44dc3..527f7c1 100644 --- a/src/test/java/io/ipdata/client/MockIpdataServer.java +++ b/src/test/java/io/ipdata/client/MockIpdataServer.java @@ -29,6 +29,7 @@ public class MockIpdataServer { private final String url; private final Map fixtures = new HashMap<>(); private final ObjectMapper mapper = new ObjectMapper(); + private volatile String lastRawPath; private MockIpdataServer() { try { @@ -54,6 +55,10 @@ public String getUrl() { return url; } + public String getLastRawPath() { + return lastRawPath; + } + private void loadFixtures() { String[] ips = {"8.8.8.8", "2001:4860:4860::8888", "1.1.1.1", "2001:4860:4860::8844", "41.128.21.123"}; for (String ip : ips) { @@ -72,6 +77,7 @@ private void handleRequest(HttpExchange exchange) throws IOException { try { String method = exchange.getRequestMethod(); String path = exchange.getRequestURI().getPath(); + lastRawPath = exchange.getRequestURI().getRawPath(); String rawQuery = exchange.getRequestURI().getRawQuery(); Map params = parseQuery(rawQuery); diff --git a/src/test/java/io/ipdata/client/TestContext.java b/src/test/java/io/ipdata/client/TestContext.java index 0aacc62..c367d3b 100644 --- a/src/test/java/io/ipdata/client/TestContext.java +++ b/src/test/java/io/ipdata/client/TestContext.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.io.CharStreams; -import feign.httpclient.ApacheHttpClient; import io.ipdata.client.service.IpdataService; import lombok.Getter; import lombok.SneakyThrows; @@ -17,7 +16,6 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; -import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; @@ -25,7 +23,7 @@ import java.net.URL; import java.util.Map; -import static com.fasterxml.jackson.databind.PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES; +import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SNAKE_CASE; import static java.lang.System.getenv; import static java.util.Arrays.asList; import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals; @@ -53,20 +51,14 @@ public TestContext(String key, String url) { this.key = key; this.url = new URL(url); mapper = new ObjectMapper(); - mapper.setPropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); + mapper.setPropertyNamingStrategy(SNAKE_CASE); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); - httpClient = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); + httpClient = HttpClientBuilder.create().build(); ipdataService = Ipdata.builder().url(this.url).key(this.key) .noCache() - .feignClient(new ApacheHttpClient(HttpClientBuilder.create() - .setSSLHostnameVerifier(new NoopHostnameVerifier()) - .build()) - ).get(); + .get(); cachingIpdataService = Ipdata.builder().url(this.url) - .feignClient(new ApacheHttpClient(HttpClientBuilder.create() - .setSSLHostnameVerifier(new NoopHostnameVerifier()) - .build())) .withDefaultCache().key(key).get(); } diff --git a/src/test/resources/io/ipdata/client/fixture.json b/src/test/resources/io/ipdata/client/fixture.json index 41488f5..3275fb2 100644 --- a/src/test/resources/io/ipdata/client/fixture.json +++ b/src/test/resources/io/ipdata/client/fixture.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "236" } diff --git a/src/test/resources/io/ipdata/client/fixtures/1.1.1.1.json b/src/test/resources/io/ipdata/client/fixtures/1.1.1.1.json index 9e57b8d..11e2002 100644 --- a/src/test/resources/io/ipdata/client/fixtures/1.1.1.1.json +++ b/src/test/resources/io/ipdata/client/fixtures/1.1.1.1.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "1500" } diff --git a/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8844.json b/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8844.json index 94b49fa..62b19c9 100644 --- a/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8844.json +++ b/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8844.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "1500" } diff --git a/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8888.json b/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8888.json index 2521f4c..766ef8c 100644 --- a/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8888.json +++ b/src/test/resources/io/ipdata/client/fixtures/2001-4860-4860--8888.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "1500" } diff --git a/src/test/resources/io/ipdata/client/fixtures/41.128.21.123.json b/src/test/resources/io/ipdata/client/fixtures/41.128.21.123.json index 593d42b..58c661a 100644 --- a/src/test/resources/io/ipdata/client/fixtures/41.128.21.123.json +++ b/src/test/resources/io/ipdata/client/fixtures/41.128.21.123.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "1500" } diff --git a/src/test/resources/io/ipdata/client/fixtures/8.8.8.8.json b/src/test/resources/io/ipdata/client/fixtures/8.8.8.8.json index 73ecd30..8ad870f 100644 --- a/src/test/resources/io/ipdata/client/fixtures/8.8.8.8.json +++ b/src/test/resources/io/ipdata/client/fixtures/8.8.8.8.json @@ -56,6 +56,7 @@ }, "threat": { "is_tor": false, + "is_vpn": false, "is_proxy": false, "is_anonymous": false, "is_known_attacker": false, @@ -63,7 +64,14 @@ "is_threat": false, "is_bogon": false, "is_icloud_relay": false, - "is_datacenter": false + "is_datacenter": false, + "blocklists": [], + "scores": { + "vpn_score": 0, + "proxy_score": 0, + "threat_score": 0, + "trust_score": 100 + } }, "count": "1500" } diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties deleted file mode 100644 index 7df36e9..0000000 --- a/src/test/resources/log4j.properties +++ /dev/null @@ -1,8 +0,0 @@ -log4j.rootLogger=DEBUG, A1 -log4j.appender.A1=org.apache.log4j.ConsoleAppender -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -# Print the date in ISO 8601 format -log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n -# Print only messages of level WARN or above in the package com.foo. -log4j.logger.io=DEBUG -log4j.logger.org.apache.http=INFO diff --git a/src/test/resources/simplelogger.properties b/src/test/resources/simplelogger.properties new file mode 100644 index 0000000..572da4d --- /dev/null +++ b/src/test/resources/simplelogger.properties @@ -0,0 +1,6 @@ +org.slf4j.simpleLogger.defaultLogLevel=debug +org.slf4j.simpleLogger.log.org.apache.http=info +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss,SSS +org.slf4j.simpleLogger.showThreadName=true +org.slf4j.simpleLogger.showShortLogName=true