Skip to content

Commit c4d1bae

Browse files
authored
Merge pull request #106 from ipinfo/silvano/eng-639-add-resproxy-support-in-ipinfonode-library
Add resproxy Residential Proxy API support
2 parents 818588f + 5343bf8 commit c4d1bae

File tree

8 files changed

+73
-5
lines changed

8 files changed

+73
-5
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"ip": "175.107.211.204",
3+
"last_seen": "2026-01-14",
4+
"percent_days_seen": 50,
5+
"service": "DataImpulse"
6+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

__tests__/ipinfoWrapper.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as dotenv from "dotenv";
2-
import { AsnResponse, IPinfo } from "../src/common";
2+
import { AsnResponse, IPinfo, Resproxy } from "../src/common";
33
import IPinfoWrapper from "../src/ipinfoWrapper";
44

55
let ipinfoWrapper: IPinfoWrapper;
@@ -195,6 +195,24 @@ describe("IPinfoWrapper", () => {
195195
expect(data.bogon).toEqual(true);
196196
});
197197

198+
test("lookupResproxy", async () => {
199+
// test multiple times for cache.
200+
for (let i = 0; i < 5; i++) {
201+
const data: Resproxy = await ipinfoWrapper.lookupResproxy(
202+
"175.107.211.204"
203+
);
204+
expect(data.ip).toEqual("175.107.211.204");
205+
expect(data.last_seen).toEqual("2026-01-14");
206+
expect(data.percent_days_seen).toEqual(50);
207+
expect(data.service).toEqual("DataImpulse");
208+
}
209+
});
210+
211+
test("lookupResproxyEmpty", async () => {
212+
const data: Resproxy = await ipinfoWrapper.lookupResproxy("8.8.8.8");
213+
expect(data).toEqual({});
214+
});
215+
198216
test("Error is thrown for invalid token", async () => {
199217
const ipinfo = new IPinfoWrapper("invalid-token");
200218
await expect(ipinfo.lookupIp("1.2.3.4")).rejects.toThrow();

__tests__/jest.setup.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ module.exports = async function globalSetup() {
3232
method: "POST",
3333
path: "/tools/map",
3434
response: path.resolve(__dirname, "./fixtures/tools/map.json")
35+
},
36+
{
37+
method: "GET",
38+
path: "/resproxy/175.107.211.204",
39+
response: path.resolve(
40+
__dirname,
41+
"./fixtures/resproxy/175.107.211.204.json"
42+
)
43+
},
44+
{
45+
method: "GET",
46+
path: "/resproxy/8.8.8.8",
47+
response: path.resolve(
48+
__dirname,
49+
"./fixtures/resproxy/8.8.8.8.json"
50+
)
3551
}
3652
]
3753
};

package-lock.json

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/common.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const HOST: string = "ipinfo.io";
22
export const HOST_LITE: string = "api.ipinfo.io/lite";
33
export const HOST_CORE: string = "api.ipinfo.io/lookup";
44
export const HOST_PLUS: string = "api.ipinfo.io/lookup";
5+
export const HOST_RESPROXY: string = "ipinfo.io/resproxy";
56

67
// cache version
78
export const CACHE_VSN: string = "1";
@@ -244,6 +245,13 @@ export interface MapResponse {
244245
reportUrl: string;
245246
}
246247

248+
export interface Resproxy {
249+
ip: string;
250+
last_seen: string;
251+
percent_days_seen: number;
252+
service: string;
253+
}
254+
247255
export interface BatchResponse {
248256
[key: string]:
249257
| IPinfo

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ export {
3131
Prefixes6,
3232
AsnResponse,
3333
MapResponse,
34-
BatchResponse
34+
BatchResponse,
35+
Resproxy
3536
} from "./common";
3637

3738
export default IPinfoWrapper;

src/ipinfoWrapper.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
AsnResponse,
1717
MapResponse,
1818
BatchResponse,
19+
Resproxy,
1920
BATCH_MAX_SIZE,
2021
BATCH_REQ_TIMEOUT_DEFAULT,
2122
REQUEST_TIMEOUT_DEFAULT,
@@ -215,6 +216,26 @@ export default class IPinfoWrapper {
215216
});
216217
}
217218

219+
/**
220+
* Lookup residential proxy information using the IP.
221+
*
222+
* @param ip IP address to check for residential proxy information.
223+
* @return Response containing Resproxy data if the IP is a residential proxy.
224+
*/
225+
public async lookupResproxy(ip: string): Promise<Resproxy> {
226+
const cacheKey = `resproxy:${ip}`;
227+
const data = await this.cache.get(IPinfoWrapper.cacheKey(cacheKey));
228+
if (data) {
229+
return data;
230+
}
231+
232+
return this.fetchApi(`resproxy/${ip}`).then(async (response) => {
233+
const resproxy = (await response.json()) as Resproxy;
234+
this.cache.set(IPinfoWrapper.cacheKey(cacheKey), resproxy);
235+
return resproxy;
236+
});
237+
}
238+
218239
/**
219240
* Get a mapping of a list of IPs on a world map.
220241
*

0 commit comments

Comments
 (0)