adds API for retrieving directory

This commit is contained in:
Marcin Czenko 2025-04-27 02:29:12 +02:00
parent 07971fd566
commit 5def89126f
No known key found for this signature in database
GPG Key ID: 33DEA0C8E30937C0

View File

@ -39,8 +39,9 @@ import ../manifest
import ../streams/asyncstreamwrapper
import ../stores
import ../utils/options
# tarballs
import ../tarballs/directorymanifest
import ../tarballs/[directorymanifest, directorydownloader, tarballnodeextensions]
import ./coders
import ./json
@ -156,6 +157,61 @@ proc retrieveCid(
if not stream.isNil:
await stream.close()
proc retrieveDirectory(
node: CodexNodeRef, cid: Cid, resp: HttpResponseRef
): Future[void] {.async: (raises: [CancelledError, HttpWriteError]).} =
## Download torrent from the node in a streaming
## manner
##
let directoryDownloader = newDirectoryDownloader(node)
var bytes = 0
try:
without directoryManifest =? (await node.fetchDirectoryManifest(cid)), err:
error "Unable to fetch Directory Metadata", err = err.msg
resp.status = Http404
await resp.sendBody(err.msg)
return
resp.addHeader("Content-Type", "application/octet-stream")
resp.setHeader(
"Content-Disposition", "attachment; filename=\"" & directoryManifest.name & "\""
)
# ToDo: add contentSize to the directory manifest
# let contentLength = codexManifest.datasetSize
# resp.setHeader("Content-Length", $(contentLength.int))
await resp.prepare(HttpResponseStreamType.Plain)
echo "streaming directory: ", cid
directoryDownloader.start(cid)
echo "streaming directory started: ", cid
await sleepAsync(1.seconds)
echo "after sleep..."
while true:
echo "getNext: ", directoryDownloader.queue.len, " entries in queue"
let data = await directoryDownloader.getNext()
echo "getNext[2]: ", data.len, " bytes"
await sleepAsync(1.seconds)
if data.len == 0:
break
bytes += data.len
await resp.sendChunk(addr data[0], data.len)
echo "out of loop: ", directoryDownloader.queue.len, " entries in queue"
await resp.finish()
codex_api_downloads.inc()
except CancelledError as exc:
info "Streaming directory cancelled", exc = exc.msg
raise exc
finally:
info "Sent bytes for directory", cid, bytes
await directoryDownloader.stop()
proc buildCorsHeaders(
httpMethod: string, allowedOrigin: Option[string]
): seq[(string, string)] =
@ -421,6 +477,25 @@ proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRoute
resp.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
await node.retrieveCid(cid.get(), local = false, resp = resp)
router.api(MethodGet, "/api/codex/v1/dir/{cid}/network/stream") do(
cid: Cid, resp: HttpResponseRef
) -> RestApiResponse:
## Download a file from the network in a streaming
## manner
##
var headers = buildCorsHeaders("GET", allowedOrigin)
if cid.isErr:
return RestApiResponse.error(Http400, $cid.error(), headers = headers)
if corsOrigin =? allowedOrigin:
resp.setCorsHeaders("GET", corsOrigin)
resp.setHeader("Access-Control-Headers", "X-Requested-With")
resp.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
await node.retrieveDirectory(cid.get(), resp = resp)
router.api(MethodGet, "/api/codex/v1/data/{cid}/network/manifest") do(
cid: Cid, resp: HttpResponseRef
) -> RestApiResponse: