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

IC-530:Canister HTTP requests #7

Merged
merged 9 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions spec/ic.did
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ type definite_canister_settings = record {
freezing_threshold : nat;
};

type http_header = record { 0: text; 1: text };

type http_response = record {
status: nat;
headers: vec http_header;
body: blob;
};

type http_request_error = variant {
no_consensus;
timeout;
bad_tls;
yotamhc marked this conversation as resolved.
Show resolved Hide resolved
invalid_url;
transform_error;
dns_error;
unreachable;
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved
conn_timeout;
};

service ic : {
create_canister : (record {
settings : opt canister_settings
Expand Down Expand Up @@ -43,6 +62,15 @@ service ic : {
delete_canister : (record {canister_id : canister_id}) -> ();
deposit_cycles : (record {canister_id : canister_id}) -> ();
raw_rand : () -> (blob);
http_request : (record {
url : text;
method : variant { get };
headers: vec http_header;
body : opt blob;
transform : opt variant {
yotamhc marked this conversation as resolved.
Show resolved Hide resolved
function: func (http_response) -> (http_response) query
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved
};
}) -> (variant { Ok : http_response; Err: opt http_request_error });
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved

// provisional interfaces for the pre-ledger world
provisional_create_canister_with_cycles : (record {
Expand Down
45 changes: 45 additions & 0 deletions spec/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1654,6 +1654,51 @@ There is no restriction on who can invoke this method.

This method takes no input and returns 32 pseudo-random bytes to the caller. The return value is unknown to any part of the IC at time of the submission of this call. A new return value is generated for each call to this method.

[#ic-http_request]
=== IC method `http_request`

This method makes an HTTP request to a given URL and returns the HTTP response, possibly after a transformation.

For security, the request is executed by multiple IC replicas (usually the entire subnet) and therefore must be _idempotent_. This means that the request must not change state at the remote server, or that the remote server has means to identify duplicated requests.
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved

The responses for all the requests must be, eventually, identical. However, it is possible that a web service would return slightly different responses for the same idempotent request. For example, it may include some unique identification or a timestamp that would vary across responses.

For this reason, the calling canister can supply a transformation function, which is used by the IC to let the canister sanitize the responses from such unique values, and therefore eventually agree on an identical response. The transformation function is executed separately by each replica on the corresponding response it has received for the request. The final response will only be available to the calling canister if enough replicas have agreed on an identical response.

Currently, only GET method is supported for HTTP requests.

For security reasons, only HTTPS connections are allowed (URLs must start with `https://`). The IC uses industry-standard root CA lists to validate certificates of remote web servers.
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved

The cost of each call to the `http_request` method is `TBD` (the `transform` should also be charged).
AlexandraZapuc marked this conversation as resolved.
Show resolved Hide resolved

The maximal size of a request URL is 2048 bytes.

The maximal size of a response is `TBD`. If a response is larger than this size, only the first `TBD` bytes will be returned. This size limit also applies to the value returned by the `transform` function.
Copy link
Contributor

Choose a reason for hiding this comment

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

“also”? Or “only”? I'd expect that larger responses can be processed and trimmed down by the transform function, as we really only have a problem with large messages when they enter consensus, and that’s post-transform.

Copy link
Contributor

Choose a reason for hiding this comment

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

@yotamhc replaced TBD with 2MiB, we can modify this value later if needed, but for the first iteration, I think it's fine. Please see also Joachim's suggestion here. Is this something that we are planning to do now or maybe later, in the following iterations?

Copy link
Contributor

Choose a reason for hiding this comment

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

@nomeata We also don't want to download too big responses (before the transform). We could have another limit for that, but opted to keep it simple for now. Do you think it's crucial to allow larger responses?

// NOTE: the size above should be up to 2MB which is the maximal size of a message in the consensus queue

The following parameters should be supplied for the call:

- `url` - the requested URL
- `method` - currently only GET is supported
- `headers` - list of HTTP request headers and their corresponding values
- `transform` - an optional function that transforms raw responses to sanitized responses. This must be a function exported by the canister itself (and not another canister).

The returned response (and the response provided to the `transform` function, if specified), contains the following fields:

- `status` - the response status (e.g., 200, 404)
- `headers` - list of HTTP response headers and their corresponding values
- `body` - the response's body

The `transform` function may, for example, transform the body in any way, add or remove headers, modify headers, etc.

// TODO: Flesh out the documentation. Some information you might want to include:
// * Can you make any HTTP request? What are the constraints?
//
// * Is there a cost associated with this call? If we know we'll charge for it, but don't know
// the exact amount, adding a placeholder would be sufficient in the first draft.
//
// * The `func` in the `transform` parameter must be a function exported by the canister itself (and not another canister).

[#ic-provisional_create_canister_with_cycles]
=== IC method `provisional_create_canister_with_cycles`

Expand Down