GraphQL API: | |
---|---|
will not work in web browsers | |
UI: |
https://api.asrank.caida.org/v2/graphiql
|
script: |
scripts/asrank-download-asn.py
(simple)
|
scripts/asrank-download.py
(complex)
| |
RESTFUL API: | https://api.asrank.caida.org/v2/restful/ |
AS Rankv2.1 is a GraphQL API interface. GraphQL allows clients to create queries that specify which values they require and contain multiple resources. GraphQL, as a strongly-typed language, allows to know what data is available, in what format and verify responses.
The User Interface (UI) can be found at http://asrank.caida.org. The Application Programming Interface version 2 (APIv2) interface is available at https://api.asrank.caida.org/v2/graphql and GraphiQL, graphic interface, can be found at https://api.asrank.caida.org/v2/graphiql.
We will be operating AS Rank APIv1 (http://as-rank.caida.org/api/v1) until March 1st, 2020, but it will no longer be updated. Current users should migrate to the v2 API before this date. Contact asrank-info@caida.org for migration assistance.
Documentation for GraphQL's query language can be found at https://graphql.org/learn/.
AS Rank API: schema
GraphQL works with the standard set of HTTP tools (see 4 simple ways to call a GraphQL API).
python3 asrank-download-asn.py 701
python3 asrank-download.py -v -a asns.jsonl -o organizations.jsonl -l asnLinks.jsonl -u https://api.asrank.caida.org/v2/graphql
curl -H "Content-Type: application/json" -X POST \ --data '{ "query": "{ asn(asn:\"701\"){ asn organization { orgName } cone { numberAsns } } }" }' \ https://api.asrank.caida.org/v2/graphql
ASRank API v2.1 supports a RESTFUL and GraphQL API. The RESTFUL does not provide any additional functionality, but a simplified interface to the GraphQL API. It will return the same data as the GraphQL.
These are really just calls to the GraphAPI interface. They do not directly talk to the Database.
A list of the supported calls is:
/restful/asns /restful/asns/:asn(\d+) /restful/asns/name/:name(.+) /restful/asnLinks /restful/asnLinks/:asn0(\d+) /restful/organizations /restful/organizations/:organization(.+)
Detailed RESTFUL doc with examples can be found here: restful/doc
For those unfamiliar with GraphQL, it is a bit of a paradigm shift from the use of a RESTful API, in that GraphQL requires the client to specify precisely which values it needs. In the following example, the client wants to know an ASN's transit degree. With a normal RESTful API, the client must retrieve the full record and extract the information it wants. A GraphQL API client must specify that it wants the ASN's transit degree.
GraphQL | RESTFUL | ||||
---|---|---|---|---|---|
|
|
GraphQL supports mixed record queries. The same query can include different record types, and can specify bindings ("joins") between those resources. This approach reduces the number of API queries needed to retrieve related resources.
GraphQL | RESTFUL | |||||
---|---|---|---|---|---|---|
mixed types | mixed and joined types | two seperate queries | ||||
# request ASN 3356's asnName and # organization LPL-141-ARIN's rank. query={ asn(asn:"3356") { asnName organization { orgId } } organization(orgId:"LPL-141-ARIN") { rank } } |
# request ASN 3356's asnName and # it's organization's rank. query={ asn(asn:"3356") { asnName organization { rank } } } |
|
See asnCone and asnConeStream scheme at doc's tab on https://api.asrank.caida.org/v2/graphiql
Any type whose name ends in “Connection” is considered by this spec to be a Connection Type. Connection types must be an “Object” as defined in the “Type System” section of the GraphQL Specification.
Connection types must have fields named edges and pageInfo. They may have additional fields related to the connection, as the schema designer sees fit.
A “Connection Type” must contain a field called edges. This field must return a list type that wraps an edge type, where the requirements of an edge type are defined in the “Edge Types” section below
A “Connection Type” must contain a field called pageInfo. This field must return a non‐null PageInfo object, as defined in the “PageInfo” section below.
Edge is the system that GraphQL uses for pagination , it is a slice of a longer list. A type that is returned in list form by a connection type’s edges field is considered by this spec to be an Edge Type. Edge types must be an “Object” as defined in the “Type System” section of the GraphQL Specification.
Edge types must have fields named node and cursor. They may have additional fields related to the edge, as the schema designer sees fit.
An “Edge Type” must contain a field called node. This field must return either a Scalar, Enum, Object, Interface, Union, or a Non‐Null wrapper around one of those types. Notably, this field cannot return a list.
An “Edge Type” must contain a field called cursor. This field must return a type that serializes as a String; this may be a String, a Non‐Null wrapper around a String, a custom scalar that serializes as a String, or a Non‐Null wrapper around a custom scalar that serializes as a String.
Whatever type this field returns will be referred to as the cursor type in the rest of this spec.
The server must provide a type called PageInfo.
PageInfo must contain fields hasPreviousPage and hasNextPage, both of which return non‐null booleans. It must also contain fields startCursor and endCursor, both of which return non‐null opaque strings
AsnCone returns the cone, where asn: is Asn whose cone is returned Query: asnCone(asn:String, dates:[String]): AsnCone
Request AsnCone query example | Response example |
---|---|
{ asnCone(asn: "2", date: "2019-12-01") { date asn { date asnName rank } cone { numberAsns } asns { totalCount pageInfo { first offset status hasPreviousPage hasNextPage } edges { node { date asn asnName } } } } } |
{ "data": { "asnCone": { "date": "2019-12-01", "asn": { "date": "2019-12-01", "asnName": "UDEL-DCN", "rank": 3452 }, "asns": { "totalCount": 5, "pageInfo": { "first": 40, "offset": 0, "status": "success", "hasPreviousPage": false, "hasNextPage": false }, "edges": [ { "node": { "date": "2019-12-01", "asn": "6147", "asnName": "" } }, { "node": { "date": "2019-12-01", "asn": "204854", "asnName": "ACMIPNETWORK-AS" } } ] } } } } |
Unlike other queries, stream does not work in units of edges. Rather it attempts to return as much information per page as possible. It will do a depth first walk of the objects requested. With that walk split across multiple pages.
AsnConeStream imitates graphql connection pagination (with a pseudocursor), allowing you to iterate over the list of external objects (cone) and the asns and prefixes objects enclosed in it as one continuous list. Moving the cursor begins with the first cone object, filtered by date or not, sequentially moving to the asns nested object and after completing the asns walk with passing through the nested prefixes object. At each step of the cursor, and the step may not necessarily be equal to one record, the information of the current and next cursor specified in three dimensions is stored in the StreamPageInfo object: index of cone, index of asn and index of prefix. For example, if the cursor was set to a step of 100 elements, then at the end of the passage StreamPageInfo will contain approximately the following information:
type StreamPageInfo { pageCursor: 12,345, nextPageCursor: 112,,46 hasNextPage: true }
where:
pageCursor is a line containing digits separated by a comma, in which the first digit is the pointer to the current Cone Id, the second digit is the Asn index in the Asns list belonging to the current Cone (12) and the third empty element signals that the cursor has not yet started navigating the Prefixes nested list , because it did not complete the passage through the Asns object.
nextPageCursor is the pointer to the start of the next cursor pass on Cones, Asns, and Prefixes objects. In this case, we see that the cursor begin its passage from Cone with Id = 12 and object with index 46 in the Prefixes list. A space between two commas indicates that the cursor has already passed all Asns objects.
Query: asnConesStream(asns:[String], asnMembers;[String], prefixMembers:[String], pageCursor:String, sort:String, dates:[String]):AsnConeStreamConnection!
Request ConeStream query example | Response example |
---|---|
{ asnConesStream(pageCursor: "") { totalCount pageInfo { pageCursor nextPageCursor hasNextPage } pages { rank asn { date asn asnName } asns { date asnName rank source cliqueMember seen ixp longitude latitude } prefixes { date network length } } } } |
{ "data": { "asnConesStream": { "totalCount": 1000, "pageInfo": { "pageCursor": "1,0,0", "nextPageCursor": "2,,860", "hasNextPage": true }, "pages": [ { "rank": 7603, "asn": { "date": "2020-02-01", "asn": "1", "asnName": "LVLT-1" }, "asns": [ { "date": "2020-02-01", "asnName": "LVLT-1", "rank": 7603, "source": "ARIN", "cliqueMember": true, "seen": true, "ixp": null, "longitude": -67.8461072038472, "latitude": 62.0485273010488 }, { "date": "2020-02-01", "asnName": "", "rank": 30443, "source": "LACNIC", "cliqueMember": true, "seen": true, "ixp": null, "longitude": -46.6295, "latitude": -23.5156 } ], "prefixes": [ { "date": "2020-02-01", "network": "4.31.236.64", "length": 29 }, { "date": "2020-02-01", "network": "4.34.12.0", "length": 24 } ... ] } ] } } } |
ASRank API v2.1 (GraphQL) supports Historic data queries.
"startDate" and "endDate" are used to define the time interval you want so search in.
Time interval is "inclusive" which means "t BETWEEN starDate AND endDate" is equivalent to "t >= starDate AND t <= endDate".
By default (if no date interval is specified) the latest month data is shown.
Sorting by "date" is supported. The default sorting is by date in ascending order.
Request Historic query example | Response example |
---|---|
{ asns(asns:["701"], dateStart:"2019-10-01", dateEnd:"2020-02-01") { edges { node { asn rank date } } } } |
{ "data": { "asns": { "edges": [ { "node": { "asn": "701", "rank": 20, "date": "2019-10-01" } }, { "node": { "asn": "701", "rank": 20, "date": "2019-11-01" } }, { "node": { "asn": "701", "rank": 20, "date": "2019-12-01" } }, { "node": { "asn": "701", "rank": 21, "date": "2020-01-01" } }, { "node": { "asn": "701", "rank": 25, "date": "2020-02-01" } } ] } } } |
Below are AS Rankv2.1 query examples.
{dataset(date:"20190501"){ datasetId, modifiedAt, date, ipVersion, country{iso, name, capital, continent}, asnReservedRanges, asnAssignedRanges, clique, asnIxs, sources{url,date,name}, numberAddresses, numberPrefixes, numberAsns, numberAsnsSeen, numberOrganizations, numberOrganizationsSeen} }
{datasets(first:10){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{ datasetId, modifiedAt, date, ipVersion, country{iso,name}, asnReservedRanges, asnAssignedRanges, clique, asnIxs, sources {url,date,name}, numberAddresses, numberPrefixes, numberAsns, numberAsnsSeen, numberOrganizations, numberOrganizationsSeen, }}}}RETRIEVE ASNS Asn sort params:
1. asn 2. asnName 3. rank 4. source 5. cone.numberAsns 6. cone.numberPrefixes 7. cone.numberAddresses 8. asnDegree.peer 9. asnDegree.customer 10. asnDegree.transit 11. asnDegree.sibling 12. asnDegree.total
{asn(asn:"3356"){ asn, asnName, organization{orgId,orgName}, asnLinks(first:10){ totalCount, pageInfo{first,offset,status,hasNextPage}, edges{node{ asn0{asn,asnName}, asn1{asn,asnName} } } }}}
{asns(first:40,name:"level",asns:["3356","2929"]){ totalCount, pageInfo{first,offset}, edges{node{ asn, asnName, rank, organization{ orgId, orgName, rank, members{ numberAsns, numberAsnsSeen, asns{ totalCount, edges{ node{asn, asnName} } } }, asnLinks(first:10){ totalCount, pageInfo{first,offset,status,hasNextPage}, edges{ node{ asn0{asn,asnName}, asn1{asn,asnName} } } } } } }}}RETRIEVE ORGANIZATIONS Organizations sort params:
1. orgId 2. orgName 3. rank 4. asnDegree.provider 5. asnDegree.peer 6. asnDegree.customer 7. asnDegree.transit 8. asnDegree.sibling 9. asnDegree.total 10. cone.numberAsns 11. cone.numberPrefixes 12. cone.numberAddresses
{organization(orgId:"LPL-141-ARIN"){ orgId, orgName, members{ numberAsns, numberAsnsSeen, asns{totalCount,edges{node{asn,asnName}}} }, asnLinks(first:20){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{ asn0{asn}, asn1{asn}}} } }}
{organizations(first:20, sort:"rank", dateStart:"20180101", dateEnd:"20191001"){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{ orgId, orgName, rank, neighbors(first:20){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{asn}} }, members{ numberAsns, numberAsnsSeen, asns{ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{asn,asnName}} } }, asnLinks(first:20){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{ asn0{asn}, asn1{asn}}} } }}}}RETRIEVE LINKS Links sort params:
1. asn0 2. asn1 3. numberPaths 4. relationship 5. correctedBy
{asnLink(asn0:"1299",asn1:"3356"){ asn0{asn,asnName}, asn1{asn,asnName}, relationship, numberPaths, locations{ totalCount, pageInfo{first,offset}, edges{ node{ locId, city, region, country population } } } }}
{asnLinks(first:10,asn:"3356"){ totalCount, pageInfo{first,offset}, edges{node{ asn1{asn,asnName}, numberPaths } }}}RETRIEVE LOCATIONS Links sort params:
1. locId 2. city 3. region 4. country 5. continent 6. population
{locations(first:10,sort:"-country,region"){ totalCount, pageInfo{status,first,offset,hasPreviousPage,hasNextPage}, edges{node{ locId, city, region, country, continent, latitude, longitude, population} } }}