Skip to content

Commit

Permalink
Merge branch 'master' into revise-readme
Browse files Browse the repository at this point in the history
  • Loading branch information
jimaek authored Dec 11, 2023
2 parents 82d047f + 92ea2cf commit 9592739
Show file tree
Hide file tree
Showing 41 changed files with 1,646 additions and 799 deletions.
8 changes: 8 additions & 0 deletions public/v1/components/examples.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ components:
"packets": 6
}
}
createMeasurementPingLocationsMeasurementId:
summary: 'ping: previous measurement id'
value:
{
"type": "ping",
"target": "cdn.jsdelivr.net",
"locations": "1wzMrzLBZfaPoT1c"
}
createMeasurementResponse:
value:
{
Expand Down
38 changes: 32 additions & 6 deletions public/v1/components/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,18 @@ components:
maximum: 200
default: 1
MeasurementLocations:
type: array
description: |
An array of locations from which to run the measurement.
Each object specifies a location using one or multiple keys.
items:
$ref: 'schemas.yaml#/components/schemas/MeasurementLocationOption'
oneOf:
- type: array
description: |
An array of locations from which to run the measurement. Each object specifies a location using one or multiple keys.
items:
$ref: 'schemas.yaml#/components/schemas/MeasurementLocationOption'
- type: string
description: |
`id` of a previous measurement - its probes are reused for the new measurement and returned in the same order.
Measurement type and options are not reused and need to be specified in the request.
Note that this option only works for the lifetime of the original measurement
and will result in a `422` response for expired or invalid `id` values.
MeasurementOptions:
anyOf:
- $ref: 'schemas.yaml#/components/schemas/MeasurementPingOptions'
Expand Down Expand Up @@ -571,6 +577,7 @@ components:
- continent
- region
- country
- state
- city
- asn
- network
Expand Down Expand Up @@ -716,6 +723,7 @@ components:
anyOf:
- $ref: 'schemas.yaml#/components/schemas/InProgressTestResult'
- $ref: 'schemas.yaml#/components/schemas/FailedTestResult'
- $ref: 'schemas.yaml#/components/schemas/OfflineTestResult'
- $ref: 'schemas.yaml#/components/schemas/FinishedPingTestResult'
- $ref: 'schemas.yaml#/components/schemas/FinishedTracerouteTestResult'
- $ref: 'schemas.yaml#/components/schemas/FinishedDnsTestResult'
Expand Down Expand Up @@ -757,6 +765,20 @@ components:
$ref: 'schemas.yaml#/components/schemas/FailedTestStatus'
rawOutput:
$ref: 'schemas.yaml#/components/schemas/TestRawOutput'
OfflineTestResult:
type: object
title: OfflineTestResult
description: |
Represents an `offline` test where the requested probe is currently offline and most fields are not available.
Only possible when passing an `id` of a previous measurement to the `locations` field.
required:
- status
- rawOutput
properties:
status:
$ref: 'schemas.yaml#/components/schemas/OfflineTestStatus'
rawOutput:
$ref: 'schemas.yaml#/components/schemas/TestRawOutput'
FinishedPingTestResult:
title: FinishedPingTestResult
allOf:
Expand Down Expand Up @@ -1118,6 +1140,10 @@ components:
allOf:
- $ref: 'schemas.yaml#/components/schemas/BaseTestStatus'
- const: failed
OfflineTestStatus:
allOf:
- $ref: 'schemas.yaml#/components/schemas/BaseTestStatus'
- const: offline
TimingPacketRtt:
type: number
description: The round-trip time for this packet.
Expand Down
3 changes: 3 additions & 0 deletions public/v1/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ paths:
- Set the `inProgressUpdates` option to `true` if the application is running in interactive mode so that the user sees the results right away.
- If the application is interactive by default but also implements a "CI" mode to be used in scripts, do not set the flag in the CI mode.
- To perform multiple measurements from exactly the same probes, create a single measurement first, then pass its `id` in the `locations` option for the other measurements.
requestBody:
content:
application/json:
Expand All @@ -61,6 +62,8 @@ paths:
$ref: 'components/examples.yaml#/components/examples/createMeasurementPingLocationsMagic'
pingCustom:
$ref: 'components/examples.yaml#/components/examples/createMeasurementPingCustom'
pingLocationsMeasurementId:
$ref: 'components/examples.yaml#/components/examples/createMeasurementPingLocationsMeasurementId'
responses:
'202':
$ref: 'components/responses.yaml#/components/responses/measurements202'
Expand Down
4 changes: 0 additions & 4 deletions src/lib/adopted-probes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ export class AdoptedProbes {
const adoptedValue = _.get(adoptedProbe, adoptedField) as string | number;
const connectedValue = _.get(connectedProbe, connectedField) as string | number;

if (!adoptedValue && !connectedValue) { // undefined and null values are treated equal and don't require sync
return;
}

if (adoptedValue !== connectedValue) {
updateObject[adoptedField] = connectedValue;
}
Expand Down
13 changes: 5 additions & 8 deletions src/lib/geoip/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { ProbeLocation } from '../../probe/types.js';
import RedisCache from '../cache/redis-cache.js';
import { getRedisClient } from '../redis/client.js';
import { scopedLogger } from '../logger.js';
import { getRegionByCountry } from '../location/location.js';
import { isAddrWhitelisted } from './whitelist.js';
import { ipinfoLookup } from './providers/ipinfo.js';
import { fastlyLookup } from './providers/fastly.js';
Expand All @@ -16,8 +15,8 @@ import { ipmapLookup } from './providers/ipmap.js';
import { type Ip2LocationBundledResponse, ip2LocationLookup } from './providers/ip2location.js';
import { isHostingOverrides } from './overrides.js';

export type LocationInfo = Omit<ProbeLocation, 'region'>;
type Provider = 'ipmap' | 'ip2location' | 'ipinfo' | 'maxmind' | 'fastly';
export type LocationInfo = ProbeLocation & {isHosting: boolean | null};
export type LocationInfoWithProvider = LocationInfo & {provider: Provider};
export type NetworkInfo = {
network: string;
Expand All @@ -32,8 +31,8 @@ export const createGeoipClient = (): GeoipClient => new GeoipClient(new RedisCac
export default class GeoipClient {
constructor (private readonly cache: CacheInterface) {}

async lookup (addr: string): Promise<ProbeLocation> {
let isHosting = undefined;
async lookup (addr: string): Promise<LocationInfo> {
let isHosting = null;
const results = await Promise
.allSettled([
this.lookupWithCache<LocationInfo>(`geoip:ipinfo:${addr}`, async () => ipinfoLookup(addr)),
Expand All @@ -43,7 +42,7 @@ export default class GeoipClient {
this.lookupWithCache<LocationInfo>(`geoip:fastly:${addr}`, async () => fastlyLookup(addr)),
])
.then(([ ipinfo, ip2location, maxmind, ipmap, fastly ]) => {
isHosting = ip2location.status === 'fulfilled' ? ip2location.value.isHosting : undefined;
isHosting = ip2location.status === 'fulfilled' ? ip2location.value.location.isHosting : null;
const fulfilled: (LocationInfoWithProvider | null)[] = [];

// Providers here are pushed in a desc prioritized order
Expand Down Expand Up @@ -82,14 +81,12 @@ export default class GeoipClient {
}
}

const region = getRegionByCountry(match.country);

return {
continent: match.continent,
country: match.country,
state: match.state,
city: match.city,
region,
region: match.region,
normalizedCity: match.normalizedCity,
asn: Number(networkMatch.asn),
latitude: Number(match.latitude),
Expand Down
7 changes: 4 additions & 3 deletions src/lib/geoip/fake-client.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { ProbeLocation } from '../../probe/types.js';
import type { LocationInfo } from './client.js';

export const fakeLookup = (): ProbeLocation => {
export const fakeLookup = (): LocationInfo => {
return {
continent: 'SA',
country: 'AR',
state: undefined,
state: null,
city: 'Buenos Aires',
region: 'South America',
normalizedCity: 'buenos aires',
Expand All @@ -13,5 +13,6 @@ export const fakeLookup = (): ProbeLocation => {
longitude: -58.3772,
network: 'InterBS S.R.L. (BAEHOST)',
normalizedNetwork: 'interbs s.r.l. (baehost)',
isHosting: null,
};
};
5 changes: 4 additions & 1 deletion src/lib/geoip/providers/fastly.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import got from 'got';
import { getRegionByCountry } from '../../location/location.js';
import { getCity } from '../city-approximation.js';
import type { LocationInfo } from '../client.js';
import {
Expand Down Expand Up @@ -38,14 +39,16 @@ export const fastlyLookup = async (addr: string): Promise<LocationInfo> => {

return {
continent: data.continent_code,
region: getRegionByCountry(data.country_code),
country: data.country_code,
state: data.country_code === 'US' ? data.region : undefined,
state: data.country_code === 'US' ? data.region : null,
city: normalizeCityNamePublic(city),
normalizedCity: normalizeCityName(city),
asn: result.as.number,
latitude: data.latitude,
longitude: data.longitude,
network: result.as.name,
normalizedNetwork: normalizeNetworkName(result.as.name),
isHosting: null,
};
};
7 changes: 4 additions & 3 deletions src/lib/geoip/providers/ip2location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import got from 'got';
import config from 'config';
import {
getContinentByCountry,
getRegionByCountry,
getStateIsoByName,
} from '../../location/location.js';
import type { LocationInfo } from '../client.js';
Expand Down Expand Up @@ -30,7 +31,6 @@ type Ip2LocationResponse = {

export type Ip2LocationBundledResponse = {
location: LocationInfo,
isHosting: boolean | undefined,
isProxy: boolean,
};

Expand All @@ -50,7 +50,8 @@ export const ip2LocationLookup = async (addr: string): Promise<Ip2LocationBundle

const location = {
continent: result.country_code ? getContinentByCountry(result.country_code) : '',
state: result.country_code === 'US' && result.region_name ? getStateIsoByName(result.region_name) : undefined,
region: result.country_code ? getRegionByCountry(result.country_code) : '',
state: result.country_code === 'US' && result.region_name ? getStateIsoByName(result.region_name) : null,
country: result.country_code ?? '',
city: normalizeCityNamePublic(city),
normalizedCity: normalizeCityName(city),
Expand All @@ -59,11 +60,11 @@ export const ip2LocationLookup = async (addr: string): Promise<Ip2LocationBundle
longitude: result.longitude ?? 0,
network: result.as ?? '',
normalizedNetwork: normalizeNetworkName(result.as ?? ''),
isHosting: result.usage_type ? HOSTING_USAGE_TYPES.includes(result.usage_type) : null,
};

return {
location,
isHosting: result.usage_type ? HOSTING_USAGE_TYPES.includes(result.usage_type) : undefined,
isProxy: result.is_proxy ?? false,
};
};
7 changes: 4 additions & 3 deletions src/lib/geoip/providers/ipinfo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import got from 'got';
import config from 'config';
import { getContinentByCountry, getStateIsoByName } from '../../location/location.js';
import { getContinentByCountry, getRegionByCountry, getStateIsoByName } from '../../location/location.js';
import type { LocationInfo } from '../client.js';
import {
normalizeCityName,
Expand Down Expand Up @@ -34,7 +34,8 @@ export const ipinfoLookup = async (addr: string): Promise<LocationInfo> => {

return {
continent: result.country ? getContinentByCountry(result.country) : '',
state: result.country === 'US' && result.region ? getStateIsoByName(result.region) : undefined,
region: result.country ? getRegionByCountry(result.country) : '',
state: result.country === 'US' && result.region ? getStateIsoByName(result.region) : null,
country: result.country ?? '',
city: normalizeCityNamePublic(city),
normalizedCity: normalizeCityName(city),
Expand All @@ -43,6 +44,6 @@ export const ipinfoLookup = async (addr: string): Promise<LocationInfo> => {
longitude: Number(lon),
network,
normalizedNetwork: normalizeNetworkName(network),
isHosting: result.privacy?.hosting,
isHosting: result.privacy?.hosting ?? null,
};
};
6 changes: 4 additions & 2 deletions src/lib/geoip/providers/ipmap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import got from 'got';
import { getContinentByCountry } from '../../location/location.js';
import { getContinentByCountry, getRegionByCountry } from '../../location/location.js';
import type { LocationInfo } from '../client.js';
import {
normalizeCityName,
Expand All @@ -24,7 +24,8 @@ export const ipmapLookup = async (addr: string): Promise<LocationInfo> => {

return {
continent: location.countryCodeAlpha2 ? getContinentByCountry(location.countryCodeAlpha2) : '',
state: location.countryCodeAlpha2 === 'US' ? location.stateAnsiCode : undefined,
region: location.countryCodeAlpha2 ? getRegionByCountry(location.countryCodeAlpha2) : '',
state: location.countryCodeAlpha2 === 'US' && location.stateAnsiCode ? location.stateAnsiCode : null,
country: location.countryCodeAlpha2 ?? '',
city: normalizeCityNamePublic(city),
normalizedCity: normalizeCityName(city),
Expand All @@ -33,5 +34,6 @@ export const ipmapLookup = async (addr: string): Promise<LocationInfo> => {
longitude: Number(location.longitude) ?? 0,
network: '',
normalizedNetwork: '',
isHosting: null,
};
};
5 changes: 4 additions & 1 deletion src/lib/geoip/providers/maxmind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
normalizeNetworkName,
} from '../utils.js';
import { getCity } from '../city-approximation.js';
import { getRegionByCountry } from '../../location/location.js';

const client = new WebServiceClient(config.get('maxmind.accountId'), config.get('maxmind.licenseKey'));

Expand Down Expand Up @@ -39,14 +40,16 @@ export const maxmindLookup = async (addr: string): Promise<LocationInfo> => {

return {
continent: data.continent?.code ?? '',
region: data.country?.isoCode ? getRegionByCountry(data.country?.isoCode) : '',
country: data.country?.isoCode ?? '',
state: data.country?.isoCode === 'US' ? data.subdivisions?.map(s => s.isoCode)[0] ?? '' : undefined,
state: data.country?.isoCode === 'US' ? data.subdivisions?.map(s => s.isoCode)[0] ?? '' : null,
city: normalizeCityNamePublic(city),
normalizedCity: normalizeCityName(city),
asn: data.traits?.autonomousSystemNumber ?? 0,
latitude: data.location?.latitude ?? 0,
longitude: data.location?.longitude ?? 0,
network: data.traits?.isp ?? '',
normalizedNetwork: normalizeNetworkName(data.traits?.isp ?? ''),
isHosting: null,
};
};
40 changes: 0 additions & 40 deletions src/lib/http/middleware/ratelimit.ts

This file was deleted.

Loading

0 comments on commit 9592739

Please sign in to comment.