Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Test

on:
push:
branches:
- "master"
pull_request:
branches:
- "master"

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: "17"
distribution: "temurin"
cache: maven

- name: Run Maven Tests
run: mvn -B test
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fields and additional request volumes see

[Click here to view the Java Spring SDK's API documentation](https://ipinfo.github.io/spring/).

⚠️ Note: This library does not currently support our newest free API https://ipinfo.io/lite. If you’d like to use IPinfo Lite, you can call the [endpoint directly](https://ipinfo.io/developers/lite-api) using your preferred HTTP client. Developers are also welcome to contribute support for Lite by submitting a pull request.
The library also supports the Lite API, see the [Lite API section](#lite-api) for more info.

## Usage

Expand Down Expand Up @@ -174,6 +174,30 @@ The `AttributeStrategy` allows the middleware to know where to store the
Any exceptions such as `RateLimitedException` is passed through Spring's error
handling system.

### Lite API

The library gives the possibility to use the [Lite API](https://ipinfo.io/developers/lite-api) too, authentication with your token is still required.

The returned details are slightly different from the Core API.

To use the Lite API you must use the `IPinfoLiteSpring`, it works in the same way as the `IPinfoSpring` class.

```java
IPinfoLiteSpring ipinfoSpring = new IPinfoLiteSpring.Builder()
// Set the IPinfo instance. By default we provide one, however you're
// allowed to change this here. Also provide your IPinfo Access Token here.
.setIPinfo(new IPinfoLite.Builder().setToken("IPINFO ACCESS TOKEN").build())
// Set the InterceptorStrategy. By default we use
// BotInterceptorStrategy.
.interceptorStrategy(new BotInterceptorStrategy())
// Set the IPStrategy. By default we use SimpleIPStrategy.
.ipStrategy(new SimpleIPStrategy())
// Set the AttributeStrategy. By default we use SessionAttributeStrategy.
.attributeStrategy(new SessionAttributeStrategy())
// Finally build it.
.build();
```

### Other Libraries

There are [official IPinfo client libraries](https://ipinfo.io/developers/libraries) available for many languages including PHP, Python, Go, Java, Ruby, and many popular frameworks such as Django, Rails, and Laravel. There are also many third-party libraries and integrations available for our API.
Expand Down
36 changes: 30 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,59 @@
<dependency>
<groupId>io.ipinfo</groupId>
<artifactId>ipinfo-api</artifactId>
<version>2.2.1</version>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.7</version>
<version>2.13.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.2.0</version>
<version>6.0.0-M2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.10</version>
<version>7.0.0-M7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.0.10</version>
<version>7.0.0-M7</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.11</version>
<version>11.0.9</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>6.0.0-M2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.18.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>7.0.0-M7</version>
<scope>test</scope>
</dependency>
</dependencies>

Expand Down
111 changes: 111 additions & 0 deletions src/main/java/io/ipinfo/spring/IPinfoLiteSpring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package io.ipinfo.spring;

import io.ipinfo.api.IPinfoLite;
import io.ipinfo.api.model.IPResponseLite;
import io.ipinfo.spring.strategies.attribute.AttributeStrategy;
import io.ipinfo.spring.strategies.attribute.SessionAttributeStrategy;
import io.ipinfo.spring.strategies.interceptor.BotInterceptorStrategy;
import io.ipinfo.spring.strategies.interceptor.InterceptorStrategy;
import io.ipinfo.spring.strategies.ip.IPStrategy;
import io.ipinfo.spring.strategies.ip.SimpleIPStrategy;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;

public class IPinfoLiteSpring implements HandlerInterceptor {

public static final String ATTRIBUTE_KEY =
"IPinfoOfficialSparkWrapper.IPResponseLite";
private final IPinfoLite ii;
private final AttributeStrategy attributeStrategy;
private final IPStrategy ipStrategy;
private final InterceptorStrategy interceptorStrategy;

IPinfoLiteSpring(
IPinfoLite ii,
AttributeStrategy attributeStrategy,
IPStrategy ipStrategy,
InterceptorStrategy interceptorStrategy
) {
this.ii = ii;
this.attributeStrategy = attributeStrategy;
this.ipStrategy = ipStrategy;
this.interceptorStrategy = interceptorStrategy;
}

public static void main(String... args) {
System.out.println(
"This library is not meant to be run as a standalone jar."
);
System.exit(0);
}

@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler
) throws Exception {
if (!interceptorStrategy.shouldRun(request)) {
return true;
}

// Don't waste an API call if we already have it.
// This should only happen for RequestAttributeStrategy and potentially
// other implementations.
if (attributeStrategy.hasLiteAttribute(request)) {
return true;
}

String ip = ipStrategy.getIPAddress(request);
if (ip == null) {
return true;
}

IPResponseLite ipResponse = ii.lookupIP(ip);
attributeStrategy.storeLiteAttribute(request, ipResponse);

return true;
}

public static class Builder {

private IPinfoLite ii = new IPinfoLite.Builder().build();
private AttributeStrategy attributeStrategy =
new SessionAttributeStrategy();
private IPStrategy ipStrategy = new SimpleIPStrategy();
private InterceptorStrategy interceptorStrategy =
new BotInterceptorStrategy();

public Builder setIPinfo(IPinfoLite ii) {
this.ii = ii;
return this;
}

public Builder attributeStrategy(AttributeStrategy attributeStrategy) {
this.attributeStrategy = attributeStrategy;
return this;
}

public Builder ipStrategy(IPStrategy ipStrategy) {
this.ipStrategy = ipStrategy;
return this;
}

public Builder interceptorStrategy(
InterceptorStrategy interceptorStrategy
) {
this.interceptorStrategy = interceptorStrategy;
return this;
}

public IPinfoLiteSpring build() {
return new IPinfoLiteSpring(
ii,
attributeStrategy,
ipStrategy,
interceptorStrategy
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.ipinfo.spring.strategies.attribute;

import io.ipinfo.api.model.IPResponse;

import io.ipinfo.api.model.IPResponseLite;
import jakarta.servlet.http.HttpServletRequest;

public interface AttributeStrategy {
Expand All @@ -16,4 +16,23 @@ default boolean hasAttribute(HttpServletRequest request) {

return false;
}

default void storeLiteAttribute(
HttpServletRequest request,
IPResponseLite response
) {
throw new UnsupportedOperationException(
"This strategy does not support IPResponseLite."
);
}

default IPResponseLite getLiteAttribute(HttpServletRequest request) {
throw new UnsupportedOperationException(
"This strategy does not support IPResponseLite."
);
}

default boolean hasLiteAttribute(HttpServletRequest request) {
return getLiteAttribute(request) != null;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
package io.ipinfo.spring.strategies.attribute;

import io.ipinfo.api.model.IPResponse;
import io.ipinfo.api.model.IPResponseLite;
import io.ipinfo.spring.IPinfoLiteSpring;
import io.ipinfo.spring.IPinfoSpring;

import jakarta.servlet.http.HttpServletRequest;

public class RequestAttributeStrategy implements AttributeStrategy {

@Override
public void storeAttribute(HttpServletRequest request, IPResponse response) {
public void storeAttribute(
HttpServletRequest request,
IPResponse response
) {
request.setAttribute(IPinfoSpring.ATTRIBUTE_KEY, response);
}

@Override
public IPResponse getAttribute(HttpServletRequest request) {
return (IPResponse) request.getAttribute(IPinfoSpring.ATTRIBUTE_KEY);
}

@Override
public void storeLiteAttribute(
HttpServletRequest request,
IPResponseLite response
) {
request.setAttribute(IPinfoLiteSpring.ATTRIBUTE_KEY, response);
}

@Override
public IPResponseLite getLiteAttribute(HttpServletRequest request) {
return (IPResponseLite) request.getAttribute(
IPinfoLiteSpring.ATTRIBUTE_KEY
);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
package io.ipinfo.spring.strategies.attribute;

import io.ipinfo.api.model.IPResponse;
import io.ipinfo.api.model.IPResponseLite;
import io.ipinfo.spring.IPinfoLiteSpring;
import io.ipinfo.spring.IPinfoSpring;

import jakarta.servlet.http.HttpServletRequest;

public class SessionAttributeStrategy implements AttributeStrategy {

@Override
public void storeAttribute(HttpServletRequest request, IPResponse response) {
public void storeAttribute(
HttpServletRequest request,
IPResponse response
) {
request.getSession().setAttribute(IPinfoSpring.ATTRIBUTE_KEY, response);
}

@Override
public IPResponse getAttribute(HttpServletRequest request) {
return (IPResponse) request.getSession().getAttribute(IPinfoSpring.ATTRIBUTE_KEY);
return (IPResponse) request
.getSession()
.getAttribute(IPinfoSpring.ATTRIBUTE_KEY);
}

@Override
public void storeLiteAttribute(
HttpServletRequest request,
IPResponseLite response
) {
request
.getSession()
.setAttribute(IPinfoLiteSpring.ATTRIBUTE_KEY, response);
}

@Override
public IPResponseLite getLiteAttribute(HttpServletRequest request) {
return (IPResponseLite) request
.getSession()
.getAttribute(IPinfoLiteSpring.ATTRIBUTE_KEY);
}
}
Loading