Skip to content

Commit

Permalink
feat: add internal http outbound transporter (#255)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra authored May 6, 2021
1 parent 2fef3aa commit 4dd950e
Show file tree
Hide file tree
Showing 17 changed files with 113 additions and 48 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const config = {
indy,
}

agent = new Agent(config, inboundTransport, outboundTransport)
const agent = new Agent(config)
```

For an example react native app that makes use of the framework see [Aries Mobile Agent React Native](https://github.com/animo/aries-mobile-agent-react-native.git)
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"events": "^3.3.0",
"js-sha256": "^0.9.0",
"reflect-metadata": "^0.1.13",
"uuid": "^8.3.0"
"uuid": "^8.3.0",
"node-fetch": "^2.6.1"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
Expand All @@ -50,7 +51,6 @@
"express": "^4.17.1",
"husky": "^5.1.3",
"jest": "^26.6.3",
"node-fetch": "^2.6.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.2.1",
"release-it": "^14.6.1",
Expand Down
36 changes: 3 additions & 33 deletions samples/__tests__/e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Agent, InboundTransporter, OutboundTransporter } from '../../src'
import { OutboundPackage, InitConfig } from '../../src/types'
import { get, post } from '../http'
import { Agent, HttpOutboundTransporter, InboundTransporter } from '../../src'
import { InitConfig } from '../../src/types'
import { get } from '../http'
import { sleep, toBeConnectedWith, waitForBasicMessage } from '../../src/__tests__/helpers'
import indy from 'indy-sdk'
import logger from '../../src/__tests__/logger'
Expand Down Expand Up @@ -149,33 +149,3 @@ class PollingInboundTransporter implements InboundTransporter {
})
}
}

class HttpOutboundTransporter implements OutboundTransporter {
private agent: Agent

public constructor(agent: Agent) {
this.agent = agent
}
public async sendMessage(outboundPackage: OutboundPackage, receiveReply: boolean) {
const { payload, endpoint } = outboundPackage

if (!endpoint) {
throw new Error(`Missing endpoint. I don't know how and where to send the message.`)
}

logger.debug(`Sending outbound message to connection ${outboundPackage.connection.id}`, outboundPackage.payload)

if (receiveReply) {
const response = await post(`${endpoint}`, JSON.stringify(payload))
if (response) {
logger.debug(`Response received:\n ${response}`)
const wireMessage = JSON.parse(response)
this.agent.receiveMessage(wireMessage)
} else {
logger.debug(`No response received.`)
}
} else {
await post(`${endpoint}`, JSON.stringify(payload))
}
}
}
6 changes: 4 additions & 2 deletions samples/mediator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import cors from 'cors'
import config from './config'
import testLogger from '../src/__tests__/logger'
import { Agent, InboundTransporter, OutboundTransporter } from '../src'
import { OutboundPackage } from '../src/types'
import { OutboundPackage, DidCommMimeType } from '../src/types'
import { MessageRepository } from '../src/storage/MessageRepository'
import { InMemoryMessageRepository } from '../src/storage/InMemoryMessageRepository'

Expand Down Expand Up @@ -32,6 +32,8 @@ class StorageOutboundTransporter implements OutboundTransporter {
public messages: { [key: string]: any } = {}
private messageRepository: MessageRepository

public supportedSchemes = []

public constructor(messageRepository: MessageRepository) {
this.messageRepository = messageRepository
}
Expand Down Expand Up @@ -59,7 +61,7 @@ const app = express()
app.use(cors())
app.use(
express.text({
type: ['application/ssi-agent-wire', 'text/plain'],
type: [DidCommMimeType.V0, DidCommMimeType.V1],
})
)
app.set('json spaces', 2)
Expand Down
2 changes: 2 additions & 0 deletions src/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ export class SubjectInboundTransporter implements InboundTransporter {
export class SubjectOutboundTransporter implements OutboundTransporter {
private subject: Subject<WireMessage>

public supportedSchemes = []

public constructor(subject: Subject<WireMessage>) {
this.subject = subject
}
Expand Down
4 changes: 2 additions & 2 deletions src/agent/Agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ import { BasicMessagesModule } from '../modules/basic-messages/BasicMessagesModu
import { LedgerModule } from '../modules/ledger/LedgerModule'

export class Agent {
protected logger: Logger
public readonly logger: Logger
public readonly agentConfig: AgentConfig
protected eventEmitter: EventEmitter
protected wallet: Wallet
protected agentConfig: AgentConfig
protected messageReceiver: MessageReceiver
protected dispatcher: Dispatcher
protected messageSender: MessageSender
Expand Down
6 changes: 5 additions & 1 deletion src/agent/AgentConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConsoleLogger, Logger, LogLevel } from '../logger'
import { InitConfig, InboundConnection } from '../types'
import { InitConfig, InboundConnection, DidCommMimeType } from '../types'

export class AgentConfig {
private initConfig: InitConfig
Expand Down Expand Up @@ -55,6 +55,10 @@ export class AgentConfig {
return this.initConfig.autoAcceptConnections ?? false
}

public get didCommMimeType() {
return this.initConfig.didCommMimeType ?? DidCommMimeType.V0
}

public getEndpoint() {
// If a mediator is used, always return that as endpoint
const didCommServices = this.inboundConnection?.connection?.theirDidDoc?.didCommServices
Expand Down
3 changes: 2 additions & 1 deletion src/agent/EnvelopeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class EnvelopeService {
const { connection, routingKeys, recipientKeys, senderVk, payload, endpoint } = outboundMessage
const { verkey, theirKey } = connection

const returnRoute = outboundMessage.payload.hasReturnRouting()
const message = payload.toJSON()

this.logger.info('outboundMessage', {
Expand All @@ -41,7 +42,7 @@ class EnvelopeService {
outboundPackedMessage = await this.wallet.pack(forwardMessage.toJSON(), [routingKey], senderVk)
}
}
return { connection, payload: outboundPackedMessage, endpoint }
return { connection, payload: outboundPackedMessage, endpoint, responseRequested: returnRoute }
}

public async unpackMessage(packedMessage: JsonWebKey): Promise<UnpackedMessageContext> {
Expand Down
3 changes: 1 addition & 2 deletions src/agent/MessageSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ class MessageSender {
if (!this.outboundTransporter) {
throw new Error('Agent has no outbound transporter!')
}
const returnRoute = outboundMessage.payload.hasReturnRouting()
const outboundPackage = await this.envelopeService.packMessage(outboundMessage)
await this.outboundTransporter.sendMessage(outboundPackage, returnRoute)
await this.outboundTransporter.sendMessage(outboundPackage)
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
import 'reflect-metadata'

export { Agent } from './agent/Agent'
export { InboundTransporter } from './transport/InboundTransporter'
export { OutboundTransporter } from './transport/OutboundTransporter'
export { encodeInvitationToUrl, decodeInvitationFromUrl } from './helpers'
export { InitConfig, OutboundPackage } from './types'

export * from './transport'
export * from './modules/basic-messages'
export * from './modules/credentials'
export * from './modules/proofs'
Expand Down
53 changes: 53 additions & 0 deletions src/transport/HttpOutboundTransporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { OutboundTransporter } from './OutboundTransporter'
import { Agent } from '../agent/Agent'
import { Logger } from '../logger'
import { OutboundPackage } from '../types'
import { fetch } from '../utils/fetch'

export class HttpOutboundTransporter implements OutboundTransporter {
private agent: Agent
private logger: Logger

public supportedSchemes = ['http', 'https']

public constructor(agent: Agent) {
this.agent = agent
this.logger = agent.logger
}

public async sendMessage(outboundPackage: OutboundPackage) {
const { payload, endpoint, responseRequested } = outboundPackage

if (!endpoint) {
throw new Error(`Missing endpoint. I don't know how and where to send the message.`)
}

this.logger.debug(
`Sending outbound message to connection ${outboundPackage.connection.id}`,
outboundPackage.payload
)

try {
const response = await fetch(endpoint, {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': this.agent.agentConfig.didCommMimeType },
})
const responseMessage = await response.text()

// TODO: do we just want to ignore messages that were
// returned if we didn't request it?
if (responseMessage && responseRequested) {
this.logger.debug(`Response received:\n ${response}`)
const wireMessage = JSON.parse(responseMessage)
this.agent.receiveMessage(wireMessage)
}
} catch (error) {
this.logger.error(`Error sending message to ${endpoint}`, {
error,
body: payload,
didCommMimeType: this.agent.agentConfig.didCommMimeType,
})
}
}
}
4 changes: 3 additions & 1 deletion src/transport/OutboundTransporter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { OutboundPackage } from '../types'

export interface OutboundTransporter {
sendMessage(outboundPackage: OutboundPackage, receiveReply: boolean): Promise<any>
supportedSchemes: string[]

sendMessage(outboundPackage: OutboundPackage): Promise<any>
}
3 changes: 3 additions & 0 deletions src/transport/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './InboundTransporter'
export * from './OutboundTransporter'
export * from './HttpOutboundTransporter'
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ type $FixMe = any

export type WireMessage = $FixMe

export enum DidCommMimeType {
V0 = 'application/ssi-agent-wire',
V1 = 'application/didcomm-envelope-enc',
}

export interface InitConfig {
host?: string
port?: string | number
Expand All @@ -23,6 +28,7 @@ export interface InitConfig {
poolName?: string
logger?: Logger
indy: typeof Indy
didCommMimeType?: DidCommMimeType
}

export interface UnpackedMessage {
Expand All @@ -48,6 +54,7 @@ export interface OutboundMessage<T extends AgentMessage = AgentMessage> {
export interface OutboundPackage {
connection: ConnectionRecord
payload: WireMessage
responseRequested?: boolean
endpoint?: string
}

Expand Down
3 changes: 3 additions & 0 deletions src/utils/environment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isNodeJS() {
return typeof process !== 'undefined' && process.release.name === 'node'
}
20 changes: 20 additions & 0 deletions src/utils/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { isNodeJS } from './environment'

// RN exposes global fetch
let fetch = global.fetch
let Headers = global.Headers
let Request = global.Request
let Response = global.Response

// NodeJS doesn't have fetch by default
if (!fetch && isNodeJS()) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const nodeFetch = require('node-fetch')

fetch = nodeFetch.default
Headers = nodeFetch.Headers
Request = nodeFetch.Request
Response = nodeFetch.Response
}

export { fetch, Headers, Request, Response }
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4526,7 +4526,7 @@ nice-try@^1.0.4:

node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==

node-gyp@^4.0.0:
Expand Down

0 comments on commit 4dd950e

Please sign in to comment.