@web5/agent
Version:
105 lines • 4.89 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { createJsonRpcRequest, parseJson } from './json-rpc.js';
import { CryptoUtils } from '@web5/crypto';
import { DwnServerInfoCacheMemory } from './dwn-server-info-cache-memory.js';
/**
* HTTP client that can be used to communicate with Dwn Servers
*/
export class HttpDwnRpcClient {
constructor(serverInfoCache) {
this.serverInfoCache = serverInfoCache !== null && serverInfoCache !== void 0 ? serverInfoCache : new DwnServerInfoCacheMemory();
}
get transportProtocols() { return ['http:', 'https:']; }
sendDwnRequest(request) {
return __awaiter(this, void 0, void 0, function* () {
const requestId = CryptoUtils.randomUuid();
const jsonRpcRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
target: request.targetDid,
message: request.message
});
const fetchOpts = {
method: 'POST',
headers: {
'dwn-request': JSON.stringify(jsonRpcRequest)
}
};
if (request.data) {
// @ts-expect-error TODO: REMOVE
fetchOpts.headers['content-type'] = 'application/octet-stream';
// @ts-expect-error TODO: REMOVE
fetchOpts['body'] = request.data;
}
const resp = yield fetch(request.dwnUrl, fetchOpts);
let dwnRpcResponse;
// check to see if response is in header first. if it is, that means the response is a ReadableStream
let dataStream;
const { headers } = resp;
if (headers.has('dwn-response')) {
// @ts-expect-error TODO: REMOVE
const jsonRpcResponse = parseJson(headers.get('dwn-response'));
if (jsonRpcResponse == null) {
throw new Error(`failed to parse json rpc response. dwn url: ${request.dwnUrl}`);
}
dataStream = resp.body;
dwnRpcResponse = jsonRpcResponse;
}
else {
// TODO: wonder if i need to try/catch this?
const responseBody = yield resp.text();
dwnRpcResponse = JSON.parse(responseBody);
}
if (dwnRpcResponse.error) {
const { code, message } = dwnRpcResponse.error;
throw new Error(`(${code}) - ${message}`);
}
const { reply } = dwnRpcResponse.result;
if (dataStream && reply.record) {
reply.record.data = dataStream;
}
else if (dataStream && reply.entry) {
reply.entry.data = dataStream;
}
return reply;
});
}
getServerInfo(dwnUrl) {
return __awaiter(this, void 0, void 0, function* () {
const serverInfo = yield this.serverInfoCache.get(dwnUrl);
if (serverInfo) {
return serverInfo;
}
const url = new URL(dwnUrl);
// add `/info` to the dwn server url path
url.pathname.endsWith('/') ? url.pathname += 'info' : url.pathname += '/info';
try {
const response = yield fetch(url.toString());
if (response.ok) {
const results = yield response.json();
// explicitly return and cache only the desired properties.
const serverInfo = {
registrationRequirements: results.registrationRequirements,
maxFileSize: results.maxFileSize,
webSocketSupport: results.webSocketSupport,
};
this.serverInfoCache.set(dwnUrl, serverInfo);
return serverInfo;
}
else {
throw new Error(`HTTP (${response.status}) - ${response.statusText}`);
}
}
catch (error) {
throw new Error(`Error encountered while processing response from ${url.toString()}: ${error.message}`);
}
});
}
}
//# sourceMappingURL=http-dwn-rpc-client.js.map