Skip to content

Commit

Permalink
chore: apply feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Oct 13, 2023
1 parent df60a7f commit 622971e
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 48 deletions.
2 changes: 1 addition & 1 deletion packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[![codecov](https://img.shields.io/codecov/c/github/ipfs/helia-routing-v1-http-api.svg?style=flat-square)](https://codecov.io/gh/ipfs/helia-routing-v1-http-api)
[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/helia-routing-v1-http-api/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/ipfs/helia-routing-v1-http-api/actions/workflows/js-test-and-release.yml?query=branch%3Amain)

> A [Delegated Routing V1](https://specs.ipfs.tech/routing/http-routing-v1/) HTTP API client
> A Delegated Routing V1 HTTP API client
## Table of contents <!-- omit in toc -->

Expand Down
2 changes: 1 addition & 1 deletion packages/client/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@helia/routing-v1-http-api-client",
"version": "1.0.2",
"description": "A Routing V1 HTTP API client",
"description": "A Delegated Routing V1 HTTP API client",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/helia-routing-v1-http-api/tree/master/packages/client#readme",
"repository": {
Expand Down
61 changes: 34 additions & 27 deletions packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import toBuffer from 'it-to-buffer'
import ndjson from 'iterable-ndjson'
import defer from 'p-defer'
import PQueue from 'p-queue'
import type { RoutingV1HttpApiClient, RoutingV1HttpApiClientInit, Record } from './index.js'
import type { RoutingV1HttpApiClient, RoutingV1HttpApiClientInit, Record, PeerRecord } from './index.js'
import type { AbortOptions } from '@libp2p/interface'
import type { PeerId } from '@libp2p/interface/peer-id'
import type { CID } from 'multiformats'
Expand Down Expand Up @@ -56,8 +56,8 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
this.started = false
}

async * getProviders (cid: CID, options: AbortOptions | undefined = {}): AsyncGenerator<Record, any, unknown> {
log('findProviders starts: %c', cid)
async * getProviders (cid: CID, options: AbortOptions = {}): AsyncGenerator<Record, any, unknown> {
log('getProviders starts: %c', cid)

const signal = anySignal([this.shutDownController.signal, options.signal, AbortSignal.timeout(this.timeout)])
const onStart = defer()
Expand Down Expand Up @@ -85,30 +85,30 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
const body = await a.json()

for (const provider of body.Providers) {
const record = this.#handleRecord(provider)
const record = this.#handleProviderRecords(provider)
if (record !== null) {
yield record
}
}
} else {
for await (const provider of ndjson(toIt(a.body))) {
const record = this.#handleRecord(provider)
const record = this.#handleProviderRecords(provider)
if (record !== null) {
yield record
}
}
}
} catch (err) {
log.error('findProviders errored:', err)
log.error('getProviders errored:', err)
} finally {
signal.clear()
onFinish.resolve()
log('findProviders finished: %c', cid)
log('getProviders finished: %c', cid)
}
}

async * getPeers (pid: PeerId, options: AbortOptions | undefined = {}): AsyncGenerator<Record, any, unknown> {
log('findPeers starts: %c', pid)
async * getPeerInfo (peerId: PeerId, options: AbortOptions | undefined = {}): AsyncGenerator<PeerRecord, any, unknown> {
log('getPeers starts: %c', peerId)

const signal = anySignal([this.shutDownController.signal, options.signal, AbortSignal.timeout(this.timeout)])
const onStart = defer()
Expand All @@ -123,7 +123,7 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
await onStart.promise

// https://specs.ipfs.tech/routing/http-routing-v1/
const resource = `${this.clientUrl}routing/v1/peers/${pid.toCID().toString()}`
const resource = `${this.clientUrl}routing/v1/peers/${peerId.toCID().toString()}`
const getOptions = { headers: { Accept: 'application/x-ndjson' }, signal }
const a = await fetch(resource, getOptions)

Expand All @@ -136,30 +136,30 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
const body = await a.json()

for (const peer of body.Peers) {
const record = this.#handleRecord(peer)
const record = this.#handlePeerRecords(peer)
if (record !== null) {
yield record
}
}
} else {
for await (const peer of ndjson(toIt(a.body))) {
const record = this.#handleRecord(peer)
const record = this.#handlePeerRecords(peer)
if (record !== null) {
yield record
}
}
}
} catch (err) {
log.error('findPeers errored:', err)
log.error('getPeers errored:', err)
} finally {
signal.clear()
onFinish.resolve()
log('findPeers finished: %c', pid)
log('getPeers finished: %c', peerId)
}
}

async getIPNS (pid: PeerId, options: AbortOptions | undefined = {}): Promise<IPNSRecord> {
log('getIPNS starts: %c', pid)
async getIPNS (peerId: PeerId, options: AbortOptions = {}): Promise<IPNSRecord> {
log('getIPNS starts: %c', peerId)

const signal = anySignal([this.shutDownController.signal, options.signal, AbortSignal.timeout(this.timeout)])
const onStart = defer()
Expand All @@ -174,7 +174,7 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
await onStart.promise

// https://specs.ipfs.tech/routing/http-routing-v1/
const resource = `${this.clientUrl}routing/v1/ipns/${pid.toCID().toString()}`
const resource = `${this.clientUrl}routing/v1/ipns/${peerId.toCID().toString()}`
const getOptions = { headers: { Accept: 'application/vnd.ipfs.ipns-record' }, signal }
const a = await fetch(resource, getOptions)

Expand All @@ -187,12 +187,12 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
} finally {
signal.clear()
onFinish.resolve()
log('getIPNS finished: %c', pid)
log('getIPNS finished: %c', peerId)
}
}

async putIPNS (pid: PeerId, record: IPNSRecord, options: AbortOptions | undefined = {}): Promise<void> {
log('getIPNS starts: %c', pid)
async putIPNS (peerId: PeerId, record: IPNSRecord, options: AbortOptions = {}): Promise<void> {
log('getIPNS starts: %c', peerId)

const signal = anySignal([this.shutDownController.signal, options.signal, AbortSignal.timeout(this.timeout)])
const onStart = defer()
Expand All @@ -209,7 +209,7 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
const body = marshal(record)

// https://specs.ipfs.tech/routing/http-routing-v1/
const resource = `${this.clientUrl}routing/v1/ipns/${pid.toCID().toString()}`
const resource = `${this.clientUrl}routing/v1/ipns/${peerId.toCID().toString()}`
const getOptions = { method: 'PUT', headers: { 'Content-Type': 'application/vnd.ipfs.ipns-record' }, body, signal }
const res = await fetch(resource, getOptions)
if (res.status !== 200) {
Expand All @@ -218,11 +218,11 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
} finally {
signal.clear()
onFinish.resolve()
log('getIPNS finished: %c', pid)
log('getIPNS finished: %c', peerId)
}
}

#handleRecord (record: any): Record | null {
#handleProviderRecords (record: any): Record | null {
if (record.Schema === 'peer') {
// Peer schema can have additional, user-defined, fields.
record.ID = peerIdFromString(record.ID)
Expand All @@ -236,10 +236,17 @@ export class DefaultRoutingV1HttpApiClient implements RoutingV1HttpApiClient {
ID: peerIdFromString(record.ID),
Addrs: record.Addrs.map(multiaddr)
}
} else if (record.Schema !== '') {
// TODO: in Go, we send unknown schemas as an UnknownRecord. I feel like
// doing this here will make it harder. Is there a way in TypeScript
// to do something like if schema === 'bitswap' then it is a BitswapRecord?
}

return null
}

#handlePeerRecords (record: any): PeerRecord | null {
if (record.Schema === 'peer') {
// Peer schema can have additional, user-defined, fields.
record.ID = peerIdFromString(record.ID)
record.Addrs = record.Addrs.map(multiaddr)
return record
}

return null
Expand Down
11 changes: 5 additions & 6 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,14 @@ import type { IPNSRecord } from 'ipns'
import type { CID } from 'multiformats/cid'

export interface PeerRecord {
Schema: string
Schema: 'peer'
ID: PeerId
Addrs: Multiaddr[]
Protocols: string[]
}

// Deprecated: please use PeerRecord instead.
export interface BitswapRecord {
Schema: string
Schema: 'bitswap'
Protocol: string
ID: PeerId
Addrs: Multiaddr[]
Expand Down Expand Up @@ -65,17 +64,17 @@ export interface RoutingV1HttpApiClient {
/**
* Returns an async generator of PeerInfos for the provided PeerId
*/
getPeers(pid: PeerId, options?: AbortOptions): AsyncGenerator<Record>
getPeerInfo(peerId: PeerId, options?: AbortOptions): AsyncGenerator<PeerRecord>

/**
* Returns a promise of a IPNSRecord for the given PeerId
*/
getIPNS(pid: PeerId, options?: AbortOptions): Promise<IPNSRecord>
getIPNS(peerId: PeerId, options?: AbortOptions): Promise<IPNSRecord>

/**
* Publishes the given IPNSRecorded for the provided PeerId
*/
putIPNS(pid: PeerId, record: IPNSRecord, options?: AbortOptions): Promise<void>
putIPNS(peerId: PeerId, record: IPNSRecord, options?: AbortOptions): Promise<void>

/**
* Shut down any currently running HTTP requests and clear up any resources
Expand Down
2 changes: 1 addition & 1 deletion packages/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[![codecov](https://img.shields.io/codecov/c/github/ipfs/helia-routing-v1-http-api.svg?style=flat-square)](https://codecov.io/gh/ipfs/helia-routing-v1-http-api)
[![CI](https://img.shields.io/github/actions/workflow/status/ipfs/helia-routing-v1-http-api/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/ipfs/helia-routing-v1-http-api/actions/workflows/js-test-and-release.yml?query=branch%3Amain)

> A [Delegated Routing V1](https://specs.ipfs.tech/routing/http-routing-v1/) HTTP API server powered by Helia
> A Delegated Routing V1 HTTP API server powered by Helia
## Table of contents <!-- omit in toc -->

Expand Down
2 changes: 1 addition & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@helia/routing-v1-http-api-server",
"version": "1.0.3",
"description": "A Routing V1 HTTP API server powered by Helia",
"description": "A Delegated Routing V1 HTTP API server powered by Helia",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/ipfs/helia-routing-v1-http-api/tree/master/packages/server#readme",
"repository": {
Expand Down
6 changes: 3 additions & 3 deletions packages/server/src/routes/routing/v1/ipns/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,20 @@ export default function getIpnsV1 (fastify: FastifyInstance, helia: Helia): void
}
},
handler: async (request, reply) => {
let pid: PeerId
let peerId: PeerId

try {
// PeerId must be encoded as a Libp2p-key CID.
const { name: cidStr } = request.params
const peerCid = CID.parse(cidStr)
pid = peerIdFromCID(peerCid)
peerId = peerIdFromCID(peerCid)
} catch (err) {
// these are .thenables but not .catchables?
reply.code(422).type('text/html').send('Unprocessable Entity') // eslint-disable-line @typescript-eslint/no-floating-promises
return
}

const rawRecord = await helia.libp2p.contentRouting.get(peerIdToRoutingKey(pid))
const rawRecord = await helia.libp2p.contentRouting.get(peerIdToRoutingKey(peerId))
reply.header('Content-Type', 'application/vnd.ipfs.ipns-record') // eslint-disable-line @typescript-eslint/no-floating-promises
return reply.send(rawRecord)
}
Expand Down
16 changes: 8 additions & 8 deletions packages/server/src/routes/routing/v1/peers/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ import type { PeerId } from '@libp2p/interface/peer-id'
import type { FastifyInstance } from 'fastify'

interface Params {
pid: string
peerId: string
}

export default function getPeersV1 (fastify: FastifyInstance, helia: Helia): void {
fastify.route<{ Params: Params }>({
method: 'GET',
url: '/routing/v1/peers/:pid',
url: '/routing/v1/peers/:peerId',
schema: {
// request needs to have a querystring with a `name` parameter
params: {
type: 'object',
properties: {
pid: {
peerId: {
type: 'string'
}
},
required: ['pid']
required: ['peerId']
}
},
handler: async (request, reply) => {
let pid: PeerId
let peerId: PeerId

try {
const { pid: cidStr } = request.params
const { peerId: cidStr } = request.params
const peerCid = CID.parse(cidStr)
pid = peerIdFromCID(peerCid)
peerId = peerIdFromCID(peerCid)
} catch (err) {
// these are .thenables but not .catchables?
reply.code(422).type('text/html').send('Unprocessable Entity') // eslint-disable-line @typescript-eslint/no-floating-promises
return
}

const peerInfo = await helia.libp2p.peerRouting.findPeer(pid)
const peerInfo = await helia.libp2p.peerRouting.findPeer(peerId)
const peerRecord = {
Schema: 'peer',
Protocols: ['transport-bitswap'],
Expand Down

0 comments on commit 622971e

Please sign in to comment.