1010import io .ipinfo .api .model .ASNResponse ;
1111import io .ipinfo .api .model .IPResponse ;
1212import io .ipinfo .api .model .MapResponse ;
13+ import io .ipinfo .api .model .ResproxyResponse ;
1314import io .ipinfo .api .request .ASNRequest ;
1415import io .ipinfo .api .request .IPRequest ;
1516import io .ipinfo .api .request .MapRequest ;
16- import okhttp3 .*;
17-
18- import javax .annotation .ParametersAreNonnullByDefault ;
17+ import io .ipinfo .api .request .ResproxyRequest ;
1918import java .io .IOException ;
2019import java .lang .reflect .Type ;
2120import java .time .Duration ;
2625import java .util .concurrent .CountDownLatch ;
2726import java .util .concurrent .TimeUnit ;
2827import java .util .function .BiConsumer ;
28+ import javax .annotation .ParametersAreNonnullByDefault ;
29+ import okhttp3 .*;
2930
3031public class IPinfo {
32+
3133 private static final int batchMaxSize = 1000 ;
3234 private static final int batchReqTimeoutDefault = 5 ;
33- private static final BatchReqOpts defaultBatchReqOpts = new BatchReqOpts .Builder ()
35+ private static final BatchReqOpts defaultBatchReqOpts =
36+ new BatchReqOpts .Builder ()
3437 .setBatchSize (batchMaxSize )
3538 .setTimeoutPerBatch (batchReqTimeoutDefault )
3639 .build ();
37- private final static Gson gson = new Gson ();
40+ private static final Gson gson = new Gson ();
3841
3942 private final OkHttpClient client ;
4043 private final Context context ;
@@ -49,7 +52,9 @@ public class IPinfo {
4952 }
5053
5154 public static void main (String ... args ) {
52- System .out .println ("This library is not meant to be run as a standalone jar." );
55+ System .out .println (
56+ "This library is not meant to be run as a standalone jar."
57+ );
5358 System .exit (0 );
5459 }
5560
@@ -61,7 +66,7 @@ public static void main(String... args) {
6166 * @throws RateLimitedException an exception when your api key has been rate limited.
6267 */
6368 public IPResponse lookupIP (String ip ) throws RateLimitedException {
64- IPResponse response = (IPResponse )cache .get (cacheKey (ip ));
69+ IPResponse response = (IPResponse ) cache .get (cacheKey (ip ));
6570 if (response != null ) {
6671 return response ;
6772 }
@@ -81,7 +86,7 @@ public IPResponse lookupIP(String ip) throws RateLimitedException {
8186 * @throws RateLimitedException an exception when your api key has been rate limited.
8287 */
8388 public ASNResponse lookupASN (String asn ) throws RateLimitedException {
84- ASNResponse response = (ASNResponse )cache .get (cacheKey (asn ));
89+ ASNResponse response = (ASNResponse ) cache .get (cacheKey (asn ));
8590 if (response != null ) {
8691 return response ;
8792 }
@@ -93,6 +98,29 @@ public ASNResponse lookupASN(String asn) throws RateLimitedException {
9398 return response ;
9499 }
95100
101+ /**
102+ * Lookup residential proxy information using the IP.
103+ *
104+ * @param ip the ip string to lookup - accepts both ipv4 and ipv6.
105+ * @return ResproxyResponse response from the api.
106+ * @throws RateLimitedException an exception when your api key has been rate limited.
107+ */
108+ public ResproxyResponse lookupResproxy (String ip )
109+ throws RateLimitedException {
110+ String cacheKeyStr = "resproxy:" + ip ;
111+ ResproxyResponse response = (ResproxyResponse ) cache .get (
112+ cacheKey (cacheKeyStr )
113+ );
114+ if (response != null ) {
115+ return response ;
116+ }
117+
118+ response = new ResproxyRequest (client , token , ip ).handle ();
119+
120+ cache .set (cacheKey (cacheKeyStr ), response );
121+ return response ;
122+ }
123+
96124 /**
97125 * Get a map of a list of IPs.
98126 *
@@ -112,9 +140,8 @@ public String getMap(List<String> ips) throws RateLimitedException {
112140 * @return the result where each URL is the key and the value is the data for that URL.
113141 * @throws RateLimitedException an exception when your API key has been rate limited.
114142 */
115- public ConcurrentHashMap <String , Object > getBatch (
116- List <String > urls
117- ) throws RateLimitedException {
143+ public ConcurrentHashMap <String , Object > getBatch (List <String > urls )
144+ throws RateLimitedException {
118145 return this .getBatchGeneric (urls , defaultBatchReqOpts );
119146 }
120147
@@ -127,8 +154,8 @@ public ConcurrentHashMap<String, Object> getBatch(
127154 * @throws RateLimitedException an exception when your API key has been rate limited.
128155 */
129156 public ConcurrentHashMap <String , Object > getBatch (
130- List <String > urls ,
131- BatchReqOpts opts
157+ List <String > urls ,
158+ BatchReqOpts opts
132159 ) throws RateLimitedException {
133160 return this .getBatchGeneric (urls , opts );
134161 }
@@ -140,10 +167,11 @@ public ConcurrentHashMap<String, Object> getBatch(
140167 * @return the result where each IP is the key and the value is the data for that IP.
141168 * @throws RateLimitedException an exception when your API key has been rate limited.
142169 */
143- public ConcurrentHashMap <String , IPResponse > getBatchIps (
144- List <String > ips
145- ) throws RateLimitedException {
146- return new ConcurrentHashMap (this .getBatchGeneric (ips , defaultBatchReqOpts ));
170+ public ConcurrentHashMap <String , IPResponse > getBatchIps (List <String > ips )
171+ throws RateLimitedException {
172+ return new ConcurrentHashMap (
173+ this .getBatchGeneric (ips , defaultBatchReqOpts )
174+ );
147175 }
148176
149177 /**
@@ -155,8 +183,8 @@ public ConcurrentHashMap<String, IPResponse> getBatchIps(
155183 * @throws RateLimitedException an exception when your API key has been rate limited.
156184 */
157185 public ConcurrentHashMap <String , IPResponse > getBatchIps (
158- List <String > ips ,
159- BatchReqOpts opts
186+ List <String > ips ,
187+ BatchReqOpts opts
160188 ) throws RateLimitedException {
161189 return new ConcurrentHashMap (this .getBatchGeneric (ips , opts ));
162190 }
@@ -169,9 +197,11 @@ public ConcurrentHashMap<String, IPResponse> getBatchIps(
169197 * @throws RateLimitedException an exception when your API key has been rate limited.
170198 */
171199 public ConcurrentHashMap <String , ASNResponse > getBatchAsns (
172- List <String > asns
200+ List <String > asns
173201 ) throws RateLimitedException {
174- return new ConcurrentHashMap (this .getBatchGeneric (asns , defaultBatchReqOpts ));
202+ return new ConcurrentHashMap (
203+ this .getBatchGeneric (asns , defaultBatchReqOpts )
204+ );
175205 }
176206
177207 /**
@@ -183,15 +213,15 @@ public ConcurrentHashMap<String, ASNResponse> getBatchAsns(
183213 * @throws RateLimitedException an exception when your API key has been rate limited.
184214 */
185215 public ConcurrentHashMap <String , ASNResponse > getBatchAsns (
186- List <String > asns ,
187- BatchReqOpts opts
216+ List <String > asns ,
217+ BatchReqOpts opts
188218 ) throws RateLimitedException {
189219 return new ConcurrentHashMap (this .getBatchGeneric (asns , opts ));
190220 }
191221
192222 private ConcurrentHashMap <String , Object > getBatchGeneric (
193- List <String > urls ,
194- BatchReqOpts opts
223+ List <String > urls ,
224+ BatchReqOpts opts
195225 ) throws RateLimitedException {
196226 int batchSize ;
197227 int timeoutPerBatch ;
@@ -201,7 +231,7 @@ private ConcurrentHashMap<String, Object> getBatchGeneric(
201231 // if the cache is available, filter out URLs already cached.
202232 result = new ConcurrentHashMap <>(urls .size ());
203233 if (this .cache != null ) {
204- lookupUrls = new ArrayList <>(urls .size ()/ 2 );
234+ lookupUrls = new ArrayList <>(urls .size () / 2 );
205235 for (String url : urls ) {
206236 Object val = cache .get (cacheKey (url ));
207237 if (val != null ) {
@@ -244,12 +274,14 @@ private ConcurrentHashMap<String, Object> getBatchGeneric(
244274
245275 // prepare latch & common request.
246276 // each request, when complete, will countdown the latch.
247- CountDownLatch latch = new CountDownLatch ((int )Math .ceil (lookupUrls .size ()/1000.0 ));
277+ CountDownLatch latch = new CountDownLatch (
278+ (int ) Math .ceil (lookupUrls .size () / 1000.0 )
279+ );
248280 Request .Builder reqCommon = new Request .Builder ()
249- .url (postUrl )
250- .addHeader ("Content-Type" , "application/json" )
251- .addHeader ("Authorization" , Credentials .basic (token , "" ))
252- .addHeader ("User-Agent" , "IPinfoClient/Java/3.2.0" );
281+ .url (postUrl )
282+ .addHeader ("Content-Type" , "application/json" )
283+ .addHeader ("Authorization" , Credentials .basic (token , "" ))
284+ .addHeader ("User-Agent" , "IPinfoClient/Java/3.2.0" );
253285
254286 for (int i = 0 ; i < lookupUrls .size (); i += batchSize ) {
255287 // create chunk.
@@ -263,57 +295,83 @@ private ConcurrentHashMap<String, Object> getBatchGeneric(
263295 String urlListJson = gson .toJson (urlsChunk );
264296 RequestBody requestBody = RequestBody .create (null , urlListJson );
265297 Request req = reqCommon .post (requestBody ).build ();
266- OkHttpClient chunkClient = client .newBuilder ()
267- .connectTimeout (timeoutPerBatch , TimeUnit .SECONDS )
268- .readTimeout (timeoutPerBatch , TimeUnit .SECONDS )
269- .build ();
270- chunkClient .newCall (req ).enqueue (new Callback () {
271- @ Override
272- @ ParametersAreNonnullByDefault
273- public void onFailure (Call call , IOException e ) {
274- latch .countDown ();
275- }
276-
277- @ Override
278- @ ParametersAreNonnullByDefault
279- public void onResponse (Call call , Response response ) throws IOException {
280- if (response .body () == null || response .code () == 429 ) {
281- return ;
282- }
298+ OkHttpClient chunkClient = client
299+ .newBuilder ()
300+ .connectTimeout (timeoutPerBatch , TimeUnit .SECONDS )
301+ .readTimeout (timeoutPerBatch , TimeUnit .SECONDS )
302+ .build ();
303+ chunkClient
304+ .newCall (req )
305+ .enqueue (
306+ new Callback () {
307+ @ Override
308+ @ ParametersAreNonnullByDefault
309+ public void onFailure (Call call , IOException e ) {
310+ latch .countDown ();
311+ }
283312
284- Type respType = new TypeToken <HashMap <String , Object >>() {}.getType ();
285- HashMap <String , Object > localResult
286- = gson .fromJson (response .body ().string (), respType );
287- localResult .forEach (new BiConsumer <String , Object >() {
288313 @ Override
289- public void accept (String k , Object v ) {
290- if (k .startsWith ("AS" )) {
291- String vStr = gson .toJson (v );
292- ASNResponse vCasted = gson .fromJson (vStr , ASNResponse .class );
293- vCasted .setContext (context );
294- result .put (k , vCasted );
295- } else if (InetAddresses .isInetAddress (k )) {
296- String vStr = gson .toJson (v );
297- IPResponse vCasted = gson .fromJson (vStr , IPResponse .class );
298- vCasted .setContext (context );
299- result .put (k , vCasted );
300- } else {
301- result .put (k , v );
314+ @ ParametersAreNonnullByDefault
315+ public void onResponse (Call call , Response response )
316+ throws IOException {
317+ if (
318+ response .body () == null ||
319+ response .code () == 429
320+ ) {
321+ return ;
302322 }
303- }
304- });
305323
306- latch .countDown ();
307- }
308- });
324+ Type respType = new TypeToken <
325+ HashMap <String , Object >
326+ >() {}.getType ();
327+ HashMap <String , Object > localResult = gson .fromJson (
328+ response .body ().string (),
329+ respType
330+ );
331+ localResult .forEach (
332+ new BiConsumer <String , Object >() {
333+ @ Override
334+ public void accept (String k , Object v ) {
335+ if (k .startsWith ("AS" )) {
336+ String vStr = gson .toJson (v );
337+ ASNResponse vCasted = gson .fromJson (
338+ vStr ,
339+ ASNResponse .class
340+ );
341+ vCasted .setContext (context );
342+ result .put (k , vCasted );
343+ } else if (
344+ InetAddresses .isInetAddress (k )
345+ ) {
346+ String vStr = gson .toJson (v );
347+ IPResponse vCasted = gson .fromJson (
348+ vStr ,
349+ IPResponse .class
350+ );
351+ vCasted .setContext (context );
352+ result .put (k , vCasted );
353+ } else {
354+ result .put (k , v );
355+ }
356+ }
357+ }
358+ );
359+
360+ latch .countDown ();
361+ }
362+ }
363+ );
309364 }
310365
311366 // wait for all requests to finish.
312367 try {
313368 if (opts .timeoutTotal == 0 ) {
314369 latch .await ();
315370 } else {
316- boolean success = latch .await (opts .timeoutTotal , TimeUnit .SECONDS );
371+ boolean success = latch .await (
372+ opts .timeoutTotal ,
373+ TimeUnit .SECONDS
374+ );
317375 if (!success ) {
318376 if (result .size () == 0 ) {
319377 return null ;
@@ -350,10 +408,11 @@ public void accept(String k, Object v) {
350408 * @return the versioned cache key.
351409 */
352410 public static String cacheKey (String k ) {
353- return k + ":1" ;
411+ return k + ":1" ;
354412 }
355413
356414 public static class Builder {
415+
357416 private OkHttpClient client = new OkHttpClient .Builder ().build ();
358417 private String token = "" ;
359418 private Cache cache = new SimpleCache (Duration .ofDays (1 ));
@@ -379,16 +438,17 @@ public IPinfo build() {
379438 }
380439
381440 public static class BatchReqOpts {
441+
382442 public final int batchSize ;
383443 public final int timeoutPerBatch ;
384444 public final int timeoutTotal ;
385445 public final boolean filter ;
386446
387447 public BatchReqOpts (
388- int batchSize ,
389- int timeoutPerBatch ,
390- int timeoutTotal ,
391- boolean filter
448+ int batchSize ,
449+ int timeoutPerBatch ,
450+ int timeoutTotal ,
451+ boolean filter
392452 ) {
393453 this .batchSize = batchSize ;
394454 this .timeoutPerBatch = timeoutPerBatch ;
@@ -397,6 +457,7 @@ public BatchReqOpts(
397457 }
398458
399459 public static class Builder {
460+
400461 private int batchSize = 1000 ;
401462 private int timeoutPerBatch = 5 ;
402463 private int timeoutTotal = 0 ;
@@ -462,7 +523,12 @@ public Builder setFilter(boolean filter) {
462523 }
463524
464525 public IPinfo .BatchReqOpts build () {
465- return new IPinfo .BatchReqOpts (batchSize , timeoutPerBatch , timeoutTotal , filter );
526+ return new IPinfo .BatchReqOpts (
527+ batchSize ,
528+ timeoutPerBatch ,
529+ timeoutTotal ,
530+ filter
531+ );
466532 }
467533 }
468534 }
0 commit comments