adds BitTorrent REST API to fetch torrent manifest only

This commit is contained in:
Marcin Czenko 2025-03-12 03:00:33 +01:00
parent ff04de52da
commit 249b799225
No known key found for this signature in database
GPG Key ID: 33DEA0C8E30937C0
2 changed files with 48 additions and 1 deletions

View File

@ -53,6 +53,11 @@ declareCounter(codex_api_downloads, "codex API downloads")
proc validate(pattern: string, value: string): int {.gcsafe, raises: [Defect].} =
0
proc formatTorrentManifest(
infoHash: MultiHash, torrentManifest: BitTorrentManifest
): RestTorrentContent =
return RestTorrentContent.init(infoHash, torrentManifest)
proc formatManifest(cid: Cid, manifest: Manifest): RestContent =
return RestContent.init(cid, manifest)
@ -210,7 +215,7 @@ proc retrieveInfoHash(
while not stream.atEof:
var
buff = newSeqUninitialized[byte](int(NBytes 1024 * 16))
buff = newSeqUninitialized[byte](BitTorrentBlockSize.int)
len = await stream.readOnce(addr buff[0], buff.len)
buff.setLen(len)
@ -545,6 +550,37 @@ proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRoute
let json = %formatManifest(cid.get(), manifest)
return RestApiResponse.response($json, contentType = "application/json")
router.api(MethodGet, "/api/codex/v1/torrent/{infoHash}/network/manifest") do(
infoHash: MultiHash, resp: HttpResponseRef
) -> RestApiResponse:
## Download only the Bit Torrent manifest (if found)
##
var headers = buildCorsHeaders("GET", allowedOrigin)
without infoHash =? infoHash.mapFailure, error:
return RestApiResponse.error(Http400, error.msg, headers = headers)
if infoHash.mcodec != Sha1HashCodec:
return RestApiResponse.error(
Http400, "Only torrents version 1 are currently supported!", headers = headers
)
without infoHashCid =? Cid.init(CIDv1, InfoHashV1Codec, infoHash).mapFailure, err:
error "Unable to create CID for BitTorrent info hash", err = err.msg
resp.status = Http404
await resp.sendBody(err.msg)
return
without torrentManifest =? (await node.fetchTorrentManifest(infoHashCid)), err:
error "Unable to fetch Torrent Manifest", err = err.msg
resp.status = Http404
await resp.sendBody(err.msg)
return
let json = %formatTorrentManifest(infoHash, torrentManifest)
return RestApiResponse.response($json, contentType = "application/json")
router.api(MethodGet, "/api/codex/v1/space") do() -> RestApiResponse:
let json =
%RestRepoStore(

View File

@ -9,6 +9,8 @@ import ../utils/json
import ../manifest
import ../units
import ../bittorrent/manifest
export json
type
@ -47,6 +49,10 @@ type
cid* {.serialize.}: Cid
manifest* {.serialize.}: Manifest
RestTorrentContent* = object
infoHash* {.serialize.}: MultiHash
torrentManifest* {.serialize.}: BitTorrentManifest
RestContentList* = object
content* {.serialize.}: seq[RestContent]
@ -81,6 +87,11 @@ proc init*(_: type RestContentList, content: seq[RestContent]): RestContentList
proc init*(_: type RestContent, cid: Cid, manifest: Manifest): RestContent =
RestContent(cid: cid, manifest: manifest)
proc init*(
_: type RestTorrentContent, infoHash: MultiHash, torrentManifest: BitTorrentManifest
): RestTorrentContent =
RestTorrentContent(infoHash: infoHash, torrentManifest: torrentManifest)
proc init*(_: type RestNode, node: dn.Node): RestNode =
RestNode(
nodeId: RestNodeId.init(node.id),