In case your canister needs to make non-replicated HTTPS requests to external APIs (both IPv4 and IPv6) you can now do so with a single inter-canister call. This reduces the cost of your outcalls by two orders of magnitude and eliminates the need of transformation functions at the cost of some extra trust assumptions.
@ilbert and I just released a proxy canister which relays the HTTPS requests via an off-chain client. The client connects to the proxy using IC WebSockets.
A high level overview of the architecture is the following:
Your canister can simply call the http_request method on the proxy canister iustv-tiaaa-aaaao-a3aga-cai with your request and a callback method (optional) which is called back by the proxy once it receives the response.
Upon receiving an inter-canister call with your request, the proxy canister relays it to the off-chain client via the IC WebSocket connection. The client makes a call to the HTTPS endpoint specified by your request.
Upon receiving the response, it sends it to the proxy which makes an inter-canister call to the callback method of your canister.
This service can be used to make a non-replicated HTTPS outcall, thus enabling you to make POST requests without having to handle idempotency. This also makes it super easy to make fire-and-forget HTTPS outcalls, simply do not specify the callback.
The off-chain client is currently controlled by us but we are planning to remove us as a single point of failure by deploying it via IC Side Services, which we will be releasing soon.
We developed this as we needed it ourselves to interact with other networks as described in IC Side Services. We decided to release it as a standalone service to see if other devs find it useful.
A general use case is when you want to make a POST to an API that does not support idempotent requests. The alternative to using this service would be to deploy your own proxy between the IC and the API in order to de-duplicate the responses.
Also, there are use cases (like the āHTTP fire-and-forgetā) in which it might make sense to trust an external service in exchange for a much cheaper and simpler way of sending requests.
I want to remark that this is not meant to substitute the IC-native HTTPS outcall feature as the trust assumptions are completely different. However, for the use cases mentioned above it might be a reasonable trade-off to make while the native feature improves.
You can interact with the basic exampleās backend cansiter from its Candid UI. Refer to the Usage section of the README for how to configure the parameters properly.
This is a great feature. I was trying to make HTTP outcalls to IPv4 addresses which isnāt supported. Or like you mentioned, when trying to make fire-and-forget calls to APIs that arenāt controlled by yourself. Itās wonderful to have this proxy server that allows for easy setup of HTTP outcalls in situations where data is just being sent out of the IC.
Really good, congrats for publishing this guys This is very much in need.
I have a few questions (since I didnāt have the opportunity to look deeper into the code).
I am assuming you will be paying the infrastructure and the proxy canister costs for now right? Itās free to use it (meaning, we only pay the first inter-canister call, to the proxy, right?). Thanks for this early invest, itās totally understandable if later you start charging as it succeeds and cost structures become more clear.
How are we safety wise? Many APIs use OAuth2, and give back the refresh/access tokens.
Letās assume I am comfortable with the IC Canister/Node risk, what is the middle-man risk (assuming itās an HTTPS Post call)?
Meaning, when is HTTPS applied (and body data encrypted), all the way from the proxy to the API Endpoint, or it decrypts on the websocket?
Yes for now we are paying for the infra and will do until we can sustain it.
Offering it as a service is something that we are considering but best would be to enable developers to deploy the needed infrastructure via an orchestrator canister. This would basically give devs the best of both worlds: they control their own infrastructure without having to deploy and maintain it themselves.
The requests are encrypted during all communications between the different components of the infrastructure (from canister to WS Gateway, to off-chain client, and to Web2 API). However, both the WS Gateway and the off-chain client (which we control) can read the requests. This is definitely not acceptable in the long run but for now itās not that far from what node providers can do.
This is very cool and I can see a thousand use cases. I will make the following cautionary note:
WARNING: If you use outcalls(other than fire and forget) you may be abandoning the cryptographic guarantees and deterministic guarantees that most expect from āclassicā crypto dapps.
These may not be necessary for your canister, and if not, then carry on, but if they are, then just keep in mind there is a bunch youāll need to consider and plan for if you want to keep those properties.
We should also push for the protocol itself to offer these kinds of outcalls, for example like composite queries. Imagine if a query or an update could make a query http outcall
Yes, operating at the protocol level is the best way to have trustless HTTP outcalls. However, I find the current state of the native feature not so practical to use, thatās why we released this service.
Not sure whether Dfinity is planning to continue the work on native HTTP outcalls right now but it would be really much needed imo.
Interesting feature! I was looking into setting up a proxy server on the IC a few months back but that didnāt work because HTTP outcalls were too slow and expensive, so this could solve/improve the issues I had. Will the mid-/long-term plan be to integrate your work into the protocol, i.e. the developer could specify that just one node should make the outcall? Maybe even with the option to do this within one query call (for any use cases where no consensus might be needed)?
This is not something to be integrated into the protocol, more like a workaround of the current limitations of the HTTP outcalls (with a big trade-off).
Improving the native HTTP outcalls would of course be amazing but we donāt have the resources to do it by ourselves now.
What we instead want to do is to deploy the off-chain client on a separate network which an orchestrator canister controls. Eventually, we are not the ones controlling the orchestrator, the HTTP proxy and off-chain client so that devs donāt have to trust us when using this service.
For a little more context, check this out. We will publish a more detailed explanation soon!
Proxying every call through a canister that uses HTTP outcalls to the intended endpoint is too slow (and likely also too expensive, but I didnāt measure that exactly) for the client, i.e. UX. So your work could decrease the costs and potentially also the time in the mid-term (depending on future plans).
Alright, thanks, just wondered if maybe you coordinated/planned to coordinate this with someone whoās working on HTTP outcalls on the protocol level and thus could potentially create some synergies there.
I learned from Bing AI that non-replicated means making http calls without waiting for many nodes to agree (which takes about 2 seconds to do). So, making http calls on IC is very fast, right?
Is Bing AI says right ?
Iām also curious if this project makes http calls easier. Is it like a web framework in some way (for example, in rust: something like Rocket web framework)?"
Not really, you have to make an inter-canister call to the proxy canister so you still have to go through consensus. Iām not sure whether there are any latency benefits. The benefits are mostly cost (inter-canister call is much cheaper than HTTP outcall) and simplicity (not having to deal with idempotency).
It makes it easier yes, but with a big trade-off.
Itās not a framework, you simply use inter-canister calls to tell the proxy canister which requests to make and which handler to trigger when it receives the response. The rest is taken care by the proxy + off-chain client. So imagine it as a service more than a framework.
I want to use the proxy canisteriustv-tiaaa-aaaao-a3aga-cai but when I call it from my own canister I get the following error: (variant {Err=variant {HttpOverWs=variant {NoProxiesConnected}}})
should I to do anything else? is the project (ic-http-proxy) yet working?