Skip to content

Add HTTP agent#76

Merged
paulyoung merged 6 commits intomasterfrom
paulyoung/js-user-library-http-agent
Oct 14, 2019
Merged

Add HTTP agent#76
paulyoung merged 6 commits intomasterfrom
paulyoung/js-user-library-http-agent

Conversation

@paulyoung
Copy link
Contributor

This adds the HTTP agent from #56, along with some refactoring. It's intended to be the lower-level interface to the HTTP API, and not the mechanism by which a typical developer interacts (at least directly) with an internet computer client.

I would like to better describe what is going on here but I need to go offline now, and wanted to at least make a PR before that.

At the moment it's a subset of what is described in the public spec. I hope the inline comments and tests can be informative until I can follow up here.

@paulyoung paulyoung requested a review from a team as a code owner October 12, 2019 00:44
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish I had more to say as a result from all the time I just spent reviewing this PR, but honestly it looks great. Well done.

}

export enum RequestStatusResponseStatus {
Pending = "pending",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stanleygjones what do you recommend we do here? I originally based everything on the spec and then realize that the client was behind, and it's been challenging to know when things have changed.

import { SubmitRequestType } from "./submitRequestType";

// The fields in a "call" submit request.
export interface CallRequest extends Request {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when we extend Request is there a standard way of ordering the fields in the encoding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the CBOR encoding? I haven't given that much thought and have been relying on the borc package for that. It seems to be deterministic though.

import { QueryRequest } from "./queryRequest";
import { RequestStatusRequest } from "./requestStatusRequest";

export type ReadRequest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public spec has a more complex structure I realized on Friday.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure I closely followed the version I was working with at the time. Is there something in particular you can point out?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary for this PR, just a mental note -- they are broken down in sync and async calls, certified, etc, instead of a flatter structure. We are missing the account balance and update canister requests, which are not applicable.

// bug in the client when the same request is submitted more than once:
// https://dfinity.atlassian.net/browse/DFN-895
nonce?: BinaryBlob;
sender_pubkey: BinaryBlob;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

particular issue?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I separated out the common fields and the auth fields because some functions ignore the auth fields.

Having all fields in the same type required me to provide values to functions just for them to be immediately removed again.

}

export type Request
= AuthFields
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

nonce?: BinaryBlob;
sender_pubkey: BinaryBlob;
sender_sig: BinaryBlob;
nonce?: Nonce;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the spec states entity_id is not always part of the common field. But I think it should be part of the request always, even if it has to move to the auth fields forever.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't realized, but the spec does say that request_type is the only field that is common to all requests, with the following being common among all asynchronous requests:

  • sender (EntityId)
  • expiry time(?)
  • nonce (blob, optional)

I think I should reflect this in the types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked into how sender (entity ID) is intended to be used enough to understand your comment about putting it in every request.

Are you proposing a change to the spec? Without that, even if we send it other implementations may not, and the client won't be able to rely on it being there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am proposing a change. I am trying to make sense of it though too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stanleygjones


window.crypto = require("@trust/webcrypto");
window.TextEncoder = require("text-encoding").TextEncoder;
require("whatwg-fetch");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this for?

Copy link
Contributor Author

@paulyoung paulyoung Oct 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing comment at the top of the file applies to this to; the browsers we're targeting will have the fetch API, but JSDom (the test environment) does not.

config: Config,
) => async (
request: ReadRequest,
): Promise<Response> => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we timeout with promise?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a promise could throw when a timeout is reached. Awaiting them requires wrapping in a try/catch block or using .catch to handle that.

@paulyoung paulyoung merged commit 240d0ce into master Oct 14, 2019
@mergify mergify bot deleted the paulyoung/js-user-library-http-agent branch October 14, 2019 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants