Skip to content
Open
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
8 changes: 8 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
maxmind:
databaseFilePath: /path/to/maxmind/database/file.mmdb
remoteIpHeader: "CLIENT-IP" #default is X-FORWARDED-FOR (when used behind a loadbalancer)
cacheTTL: 120 #In seconds, Default is 300 seconds
cacheMaxEntries: 102400 #Default is 10240
enterprise: true #default: false. Enable maxmind enterprise database mode
type: anonymous #If it is not a enterprise database; set the type of database that is being used. Supported: country, city, anonymous
maxMindContext: false #If you need MaxMindInfo injection into resource methods; set it to true
10 changes: 6 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<dropwizard.version>1.3.13</dropwizard.version>
<dropwizard.version>2.0.16</dropwizard.version>
<geoip2.version>2.12.0</geoip2.version>
<lombok.version>1.18.8</lombok.version>
<junit.version>4.12</junit.version>
<junit.version>5.7.0</junit.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
Expand Down Expand Up @@ -83,11 +83,13 @@
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

</dependencies>
</project>
19 changes: 4 additions & 15 deletions src/main/java/io/dropwizard/maxmind/geoip2/MaxMindBundle.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,17 @@
import io.dropwizard.Configuration;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.maxmind.geoip2.config.MaxMindConfig;
import io.dropwizard.maxmind.geoip2.feature.MaxMindContextFeature;
import io.dropwizard.maxmind.geoip2.filter.MaxMindGeoIpRequestFilter;
import io.dropwizard.maxmind.geoip2.provider.MaxMindContext;
import io.dropwizard.maxmind.geoip2.provider.MaxMindInfoProvider;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import org.glassfish.hk2.api.InjectionResolver;
import org.glassfish.hk2.api.TypeLiteral;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.spi.internal.ValueFactoryProvider;
import lombok.extern.slf4j.Slf4j;

import javax.inject.Singleton;

/**
* @author phaneesh
*/
@Slf4j
public abstract class MaxMindBundle<T extends Configuration> implements ConfiguredBundle<T> {

public abstract MaxMindConfig getMaxMindConfig(final T configuration);
Expand All @@ -47,14 +43,7 @@ public void run(final T configuration, final Environment environment) {
MaxMindConfig maxMindConfig = getMaxMindConfig(configuration);
environment.jersey().register(new MaxMindGeoIpRequestFilter(maxMindConfig));
if(maxMindConfig.isMaxMindContext()) {
environment.jersey().register(new AbstractBinder() {
@Override
protected void configure() {
bind(MaxMindInfoProvider.class).to(ValueFactoryProvider.class).in(Singleton.class);
bind(MaxMindInfoProvider.InjectResolver.class).to(
new TypeLiteral<InjectionResolver<MaxMindContext>>() {}).in(Singleton.class);
}
});
environment.jersey().register(MaxMindContextFeature.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.dropwizard.maxmind.geoip2.feature;

import io.dropwizard.maxmind.geoip2.provider.MaxMindContextValueParamProvider;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;

public class MaxMindContextFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
context.register(new AbstractBinder() {
@Override
protected void configure() {
bind(MaxMindContextValueParamProvider.class)
.to(ValueParamProvider.class);
}
});

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,58 +21,55 @@
import io.dropwizard.maxmind.geoip2.core.MaxMindHeaders;
import io.dropwizard.maxmind.geoip2.core.MaxMindInfo;
import lombok.extern.slf4j.Slf4j;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.server.internal.inject.AbstractValueFactoryProvider;
import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
import org.glassfish.jersey.server.internal.inject.ParamInjectionResolver;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;


import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

/**
* @author phaneesh
*/
@Slf4j
@Singleton
@Provider
public class MaxMindInfoProvider extends AbstractValueFactoryProvider {


public static final class InjectResolver extends ParamInjectionResolver<MaxMindContext> {
public class MaxMindContextValueParamProvider implements ValueParamProvider {

public InjectResolver() {
super(MaxMindInfoProvider.class);
@Override
public Function<ContainerRequest, ?> getValueProvider(Parameter parameter) {
if (parameter.getRawType().equals(MaxMindInfo.class)
&& parameter.isAnnotationPresent(MaxMindContext.class)) {
return new MaxMindInfoParamProvider();
}
return null;
}
public static final class MaxMindInfoParamProvider implements Function<ContainerRequest,MaxMindInfo> {

private static final class MaxMinfInfoParamValueFactory extends AbstractContainerRequestValueFactory<MaxMindInfo> {

@Context
private ResourceContext context;

public MaxMindInfo provide() {
final HttpServletRequest request = context.getResource(HttpServletRequest.class);
final String anonymousIp = request.getHeader(MaxMindHeaders.X_ANONYMOUS_IP);
final String anonymousVpn = request.getHeader(MaxMindHeaders.X_ANONYMOUS_VPN);
final String tor = request.getHeader(MaxMindHeaders.X_TOR);
final String city = request.getHeader(MaxMindHeaders.X_CITY);
final String state = request.getHeader(MaxMindHeaders.X_STATE);
final String stateIso = request.getHeader(MaxMindHeaders.X_STATE_ISO);
final String postal = request.getHeader(MaxMindHeaders.X_POSTAL);
final String connectionType = request.getHeader(MaxMindHeaders.X_CONNECTION_TYPE);
final String userType = request.getHeader(MaxMindHeaders.X_USER_TYPE);
final String country = request.getHeader(MaxMindHeaders.X_COUNTRY);
final String countryIso = request.getHeader(MaxMindHeaders.X_COUNTRY_ISO);
final String isp = request.getHeader(MaxMindHeaders.X_ISP);
final String latitude = request.getHeader(MaxMindHeaders.X_LATITUDE);
final String longitude = request.getHeader(MaxMindHeaders.X_LONGITUDE);
final String accuracy = request.getHeader(MaxMindHeaders.X_LOCATION_ACCURACY);
@Override
public MaxMindInfo apply(@Context ContainerRequest request) {
final String anonymousIp = getHeader(request,MaxMindHeaders.X_ANONYMOUS_IP);
final String anonymousVpn = getHeader(request,MaxMindHeaders.X_ANONYMOUS_VPN);
final String tor = getHeader(request,MaxMindHeaders.X_TOR);
final String city = getHeader(request,MaxMindHeaders.X_CITY);
final String state = getHeader(request,MaxMindHeaders.X_STATE);
final String stateIso = getHeader(request,MaxMindHeaders.X_STATE_ISO);
final String postal = getHeader(request,MaxMindHeaders.X_POSTAL);
final String connectionType = getHeader(request,MaxMindHeaders.X_CONNECTION_TYPE);
final String userType = getHeader(request,MaxMindHeaders.X_USER_TYPE);
final String country = getHeader(request,MaxMindHeaders.X_COUNTRY);
final String countryIso = getHeader(request,MaxMindHeaders.X_COUNTRY_ISO);
final String isp = getHeader(request,MaxMindHeaders.X_ISP);
final String latitude = getHeader(request,MaxMindHeaders.X_LATITUDE);
final String longitude = getHeader(request,MaxMindHeaders.X_LONGITUDE);
final String accuracy = getHeader(request,MaxMindHeaders.X_LOCATION_ACCURACY);
return MaxMindInfo.builder()
.anonymousIp(Strings.isNullOrEmpty(anonymousIp) ? false : Boolean.valueOf(anonymousIp))
.anonymousVpn(Strings.isNullOrEmpty(anonymousVpn) ? false : Boolean.valueOf(anonymousVpn))
Expand All @@ -91,21 +88,17 @@ public MaxMindInfo provide() {
.accuracy(Strings.isNullOrEmpty(accuracy) ? 0 : Integer.valueOf(accuracy))
.build();
}
private String getHeader(ContainerRequest request,String name) {
List<String> headerList = request.getRequestHeader(name);
return Optional.ofNullable(headerList)
.map(Collection::stream)
.orElseGet(Stream::empty)
.findFirst()
.orElse(null);
}
}

@Inject
public MaxMindInfoProvider(MultivaluedParameterExtractorProvider extractorProvider, ServiceLocator locator) {
super(extractorProvider, locator, Parameter.Source.UNKNOWN);
}

@Override
protected AbstractContainerRequestValueFactory<?> createValueFactory(Parameter parameter) {
Class<?> classType = parameter.getRawType();

if (classType == null || (!classType.equals(MaxMindInfo.class))) {
log.warn("MaxMindContext annotation was not placed on correct object type; Injection might not work correctly!");
return null;
}
return new MaxMinfInfoParamValueFactory();
public PriorityType getPriority() {
return Priority.HIGH;
}
}