Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

Commit

Permalink
feat: rest client worker for aries JS
Browse files Browse the repository at this point in the history
- Switching JS source from `../dist/web` to `../dist/rest` will make
aries js worker to run in rest agent client mode.
- Web worker will be using agent rest client endpoints instead of
aries wasm command handlers.
- Except worker javascript, all the other functionalities and interfaces
will remain same.
- added switch (to REST/WASM worker) feature in presentation html for
demonstration/testing.

//TODO :Currently incoming topics/messages should be looked up in
webhook URL of corresponding REST agent, javascript notifier listening
to webhook URL will be added in future.

Signed-off-by: sudesh.shetty <sudesh.shetty@securekey.com>
  • Loading branch information
sudeshrshetty committed Feb 22, 2020
1 parent bbcc187 commit 147442b
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 4 deletions.
29 changes: 29 additions & 0 deletions cmd/aries-js-worker/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,38 @@
}
}

function changeSource(src) {
//stop existing worker before switching
if (aries) {
destroyAries()
}

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.src= `dist/${src}/aries.js`;
head.appendChild(script);

const mode = (src == "rest") ? "REST" : "WASM"
document.getElementById("mode-label").innerHTML = `Running in ${mode} mode`

if (src == "rest"){
document.getElementById("opts").innerHTML = `{"assetsPath": "/dist/assets", "agent-rest-url": "http://localhost:8082"}`
} else {
document.getElementById("opts").innerHTML = `{"assetsPath": "/dist/assets", "agent-default-label":"dem-js-agent","http-resolver-url":[],"auto-accept":true,"outbound-transport":["ws","http"],"transport-return-route":"all","log-level":"debug"}`
}
}


</script>
</head>
<body>
<div>
<fieldset>
<legend id="mode-label" style="font-size: medium;font-weight: bold">Running in WASM Mode...</legend>
<button onClick="changeSource('rest')" style="font-size: large">Switch to REST version</button>
<button onClick="changeSource('web')" style="font-size: large">Switch to WASM version</button>
</fieldset>
</div>
<div>
<table>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion cmd/aries-js-worker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
)

const (
wasmStartupTopic = "wasm-ready"
wasmStartupTopic = "asset-ready"
handleResultFn = "handleResult"
ariesCommandPkg = "aries"
ariesStartFn = "Start"
Expand Down
8 changes: 6 additions & 2 deletions cmd/aries-js-worker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
"scripts": {
"build:node": "webpack --config ./webpack.config.node.js --mode=production",
"build:web": "webpack --config ./webpack.config.web.js --mode=production",
"build:rest": "webpack --config ./webpack.config.rest.js --mode=production",
"build:assets": "bash scripts/build_assets.sh",
"build": "rm -rf dist/* && cp -p ../../LICENSE . && npm run build:assets && npm run build:node && npm run build:web",
"build": "rm -rf dist/* && cp -p ../../LICENSE . && npm run build:assets && npm run build:node && npm run build:web && npm run build:rest",
"prepare": "npm run build",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand Down Expand Up @@ -37,12 +38,15 @@
"copy-webpack-plugin": "5.1.1",
"file-loader": "5.0.2",
"webpack": "4.41.5",
"webpack-cli": "3.3.10",
"webpack-cli": "^3.3.10",
"webpack-merge": "4.2.2",
"webpack-shell-plugin": "0.5.0"
},
"engines": {
"node": ">=12.14",
"npm": ">=6.13"
},
"dependencies": {
"axios": "^0.19.2"
}
}
132 changes: 132 additions & 0 deletions cmd/aries-js-worker/src/agent-rest-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/


import axios from 'axios';

// All REST endpoints provided by agent controller
const pkgs = {
didexchange: {
CreateInvitation: {
path: "/connections/create-invitation",
method: "POST"
},
ReceiveInvitation: {
path: "/connections/receive-invitation",
method: "POST"
},
AcceptInvitation: {
path: "/connections/{id}/accept-invitation",
method: "POST",
pathParam:"id"
},
AcceptExchangeRequest: {
path: "/connections/{id}/accept-request",
method: "POST",
pathParam:"id"
},
CreateImplicitInvitation: {
path: "/connections/create-implicit-invitation",
method: "POST"
},
RemoveConnection: {
path: "/connections/{id}/remove",
method: "POST",
pathParam:"id"
},
QueryConnectionByID: {
path: "/connections/{id}",
method: "GET",
pathParam:"id"
},
QueryConnections: {
path: "/connections",
method: "GET"
},
},
vdri: {
CreatePublicDID: {
path: "/vdri/create-public-did",
method: "POST"
},
},
messaging: {
RegisteredServices: {
path: "/message/services",
method: "GET"
},
RegisterMessageService: {
path: "/message/register-service",
method: "POST"
},
RegisterHTTPMessageService: {
path: "/http-over-didcomm/register",
method: "POST"
},
UnregisterMessageService: {
path: "/message/unregister-service",
method: "POST"
},
SendNewMessage: {
path: "/message/send",
method: "POST"
},
SendReplyMessage: {
path: "/message/reply",
method: "POST"
},
},
route: {
Register: {
path: "/route/register",
method: "POST"
},
Unregister: {
path: "/route/unregister",
method: "DELETE"
},
GetConnection: {
path: "/route/connection",
method: "GET"
},
},
}

/**
* Agent rest client for given agent endpoint
* @param url is rest endpoint url
* @class
*/
export const Client = class {
constructor(url) {
this.url = url
}

async handle(request) {
const r = (pkgs[request.pkg]) ? pkgs[request.pkg][request.fn] : null;
if (!r) {
return "unable to find given pkg/fn:"+request.pkg+"/"+request.fn;
}

let url = this.url + r.path
if (r.pathParam){
const p = ((request.payload[r.pathParam])) ? (request.payload[r.pathParam]) : "";
url = this.url + r.path.replace("{"+r.pathParam+"}", p);
}

console.debug(`[${r.method}] ${url}, request ${JSON.stringify(request.payload)}`)

const resp = await axios({
method: r.method,
url: url,
data: request.payload
});

return resp.data;
}
};


2 changes: 1 addition & 1 deletion cmd/aries-js-worker/src/aries.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ const Aries = function(opts) {
// return promise which waits for worker to load and aries to start.
return new Promise((resolve, reject) => {
const timer = setTimeout(_ => reject(new Error("timout waiting for aries to initialize")), 10000)
notifications.set("wasm-ready", async (result) => {
notifications.set("asset-ready", async (result) => {
clearTimeout(timer)
invoke(aw, pending, "aries", "Start", opts, "timeout while starting aries").then(
resp => resolve(),
Expand Down
70 changes: 70 additions & 0 deletions cmd/aries-js-worker/src/worker-impl-rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

self.importScripts("./agent-rest-client.js")

postMessage({topic: "asset-ready"})

// TODO synchronized access to controller
let handler, controller

const ariesHandle = {
aries: {
Start: (data) => {
if (controller) {
return newResponse(data.id, null, "aries already started");
}

if (!data.payload["agent-rest-url"]) {
return newResponse(data.id, null, "'agent-rest-url' is required");
}

controller = new RESTAgent.Client(data.payload["agent-rest-url"]);
return newResponse(data.id, "aries is started");
},
Stop: (data) => {
if (!controller) {
return newResponse(data.id, null, "aries already stopped");
}
controller = null;
return newResponse(data.id, "aries stopped");
}
}
}

onmessage = async function (e) {
console.debug('message received :', e.data);
if (ariesHandle[e.data.pkg] && ariesHandle[e.data.pkg][e.data.fn]) {
postMessage(ariesHandle[e.data.pkg][e.data.fn](e.data));
return;
}

if (controller) {
try{
const response = await controller.handle(e.data);
postMessage(newResponse(e.data.id, response));
console.debug("response from rest controller", response);
} catch(error){
console.debug("error from rest controller", error.response);
postMessage(newResponse(e.data.id, null, JSON.stringify(error.response.data)));
}
return;
}

postMessage(newResponse(e.data.id, null, "aries not started"));
}


function newResponse(id, payload, errMsg, topic) {
const isErr = (errMsg) ? true : false;
return {
id: id,
payload: payload,
isErr: isErr,
errMsg: errMsg,
topic: topic
};
}
30 changes: 30 additions & 0 deletions cmd/aries-js-worker/src/worker-loader-rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

export function loadWorker(pending, notifications, paths) {
const workerJS = paths.dir + "/worker-impl-rest.js"
const worker = new Worker(workerJS)
worker.onmessage = e => {
const result = e.data
if (result.topic){
if (notifications.get(result.topic)) {
notifications.get(result.topic)(result)
} else if (notifications.get("all")){
notifications.get("all")(result)
} else {
console.log("no subscribers found for this topic", result.topic)
}
return
}
const cb = pending.get(result.id)
pending.delete(result.id)
cb(result)
}
worker.onerror = e => {
throw new Error("aries: failed to load worker: " + e.message)
}
return worker
}
54 changes: 54 additions & 0 deletions cmd/aries-js-worker/webpack.config.rest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

const path = require("path")

const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const WebpackShellPlugin = require('webpack-shell-plugin')

const { PATHS } = require("./webpack.config.common.js")

const OUTPUT = path.join(PATHS.buildDir, "rest/")

const restConfig = {
entry: path.join(PATHS.srcDir, "aries.js"),
target: 'web',
output: {
path: OUTPUT,
publicPath: "dist/rest",
libraryTarget: "umd",
filename: 'aries.js',
library: 'Aries'
},
plugins: [
new CleanWebpackPlugin(),
new WebpackShellPlugin({
onBuildStart: [
"mkdir -p " + OUTPUT,
"cp -p src/worker-impl-rest.js dist/assets"
]
})
],
resolve: {
alias: {
worker_loader$: path.join(PATHS.srcDir, "worker-loader-rest.js"),
},
mainFields: ['browser', 'module', 'main']
}
}

const assetConfig = {
entry: path.join(PATHS.srcDir, "agent-rest-client.js"),
target: 'webworker',
output: {
path: path.resolve(PATHS.buildDir, 'assets'),
publicPath: "dist/assets",
filename: 'agent-rest-client.js',
library: "RESTAgent"
},
}

module.exports = [ restConfig, assetConfig ];

0 comments on commit 147442b

Please sign in to comment.