# Feature request: map appropriate HTTP request methods to update calls

**URL:** <https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303>\
**Category:** Developers\
**Created:** [May 25, 2021, 12:58am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303 "2021-05-25T00:58:52Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [May 25, 2021, 12:58am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/1 "2021-05-25T00:58:52Z")

</div>

I brought this up here but that thread has gotten long and there are multiple conversations happening:

> [@Can we somehow achieve or build a canister with a interface bahaving like a classic web server](https://forum.dfinity.org/t/can-we-somehow-achieve-or-build-a-canister-with-a-interface-bahaving-like-a-classic-web-server/1257/46):
>
> In agent-rs, all requests to canisters implementing the HTTP interface are converted to query calls: It seems like it should be trivial to inspect the request method and convert POST/PUT/DELETE/etc to an update call instead, but I’m assuming this code is only for development purposes and won’t affect the HTTP gateway on the network. I took a look at dfn\_http but I haven’t been able to figure out how/where that’s used or intended to be used. I would contact the author but everything appear…

I would like to request that appropriate HTTP request methods are mapped to `update` calls instead of `query`.

I think at least `POST`, `PUT`, `PATCH`, and `DELETE` would be a great start.

I could make a PR to `agent-rs` to do this but it would need the equivalent support in replicas.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [May 25, 2021, 7:27am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/2 "2021-05-25T07:27:08Z")

</div>

> [@Can we somehow achieve or build a canister with a interface bahaving like a classic web server](https://forum.dfinity.org/t/can-we-somehow-achieve-or-build-a-canister-with-a-interface-bahaving-like-a-classic-web-server/1257/53):
>
> I think these are both feature requests for the replica though.

Actually, the HTTP handling is done by the `icx-proxy` component in the `agent-rs` repo, which already is open source, so a feature request there is not inappropriate.

Turning `POST` into an update call is certainly a possibility. I think we have hesitated because maybe not every `POST` should be an update call? Imagine an image transcoding service – you probably upload the file with `POST`, but maybe still want the performance of a query call. Also, despite best intentions in the HTTP spec, in practice you might want state modification on `GET` as well in some cases.

So tying it to the method seems a bit too rigid.

In my prototype, a query call is done first, and but it can tell the proxy to upgrade to an update call, but it’s also not clear if that’s ideal.

If you don’t mind having an URL that is _not_ `*.ic0.app`, at least for experimentation, you can run a patched `icx-proxy` on your own infrastructure, and use that. The HTTP handling sits nicely on top of the core IC, instead of being a feature you can’t extract.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [May 25, 2021, 3:58pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/3 "2021-05-25T15:58:09Z")

</div>

> [@nomeata](#):
>
> Actually, the HTTP handling is done by the `icx-proxy` component in the `agent-rs` repo, which already is open source, so a feature request there is not inappropriate.

This is great news. Since I’m going to do this anyway I’ll probably make a PR and then it can be debated there 😄

In one of my use cases I could possibly run a forked version but it would be a lot neater not to.

> [@nomeata](#):
>
> in practice you might want state modification on `GET` as well in some cases.

My plan was to make the mapping configurable but with some defaults that match the intentions of the HTTP spec.

That way, different instances of the proxy could be configured differently on start up. It could even be as granular as mapping a specific route to a certain call rather than the entire request method.

> [@nomeata](#):
>
> Imagine an image transcoding service – you probably upload the file with `POST` , but maybe still want the performance of a query call.

Could you help me understand how that would work? I thought an `update` call is the only way to modify state.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [May 25, 2021, 4:10pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/4 "2021-05-25T16:10:19Z")

</div>

> [@paulyoung](#):
>
> > [@nomeata](#):
> >
> > Imagine an image transcoding service – you probably upload the file with `POST` , but maybe still want the performance of a query call.
> 
> Could you help me understand how that would work? I thought an `update` call is the only way to modify state.

That’s what I mean with a image transcoding: You `POST` a `.gif`, it returns a `.jpg`, but doesn’t actually store anything. Not saying it’s a great example for an on-IC-app, but maybe still can serve as an example for a `POST` call that you want to get query-called.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [May 27, 2021, 9:20am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/5 "2021-05-27T09:20:09Z")

</div>

> [@paulyoung](#):
>
> > [@nomeata](#):
> >
> > Actually, the HTTP handling is done by the `icx-proxy` component in the `agent-rs` repo, which already is open source, so a feature request there is not inappropriate.
> 
> This is great news. Since I’m going to do this anyway I’ll probably make a PR and then it can be debated there 😄

I forked `agent-rs` and ran it locally, with the change I proposed at the top of this thread.

I encountered 2 problems:

1. Without a `query` annotation on `http_request`, I get `Replica Error (3): "IC0302: Canister rrkah-fqaaa-aaaaa-aaaaq-cai has no query method 'http_request'"`

2. When making an update call via `http_request` I get `500 Internal Server Error` on the client and see `WARN Internal Error during request: CertificateVerificationFailed` on the server.

It looks like #1 would require a change to the replica code to allow `http_request` to have a `shared` annotation.

I haven’t been able to figure out #2 yet.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [May 27, 2021, 12:14pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/6 "2021-05-27T12:14:29Z")

</div>

Re #1: I suggest that your fork uses a different method name (`http_update_request`). It can have the same implementation, but the system (rightfully) rejects query calls to methods that aren’t marked query.

The `replica` is not involved here, this is a higher level feature (e.g. you can tell that [The Internet Computer Interface Specification :: Internet Computer](https://sdk.dfinity.org/docs/interface-spec/index.html) doesn’t mention it).

Re #2: You probably have to call [`fetch_root_key`](https://agent-rust.netlify.app/ic_agent/agent/struct.agent#method.fetch_root_key) in the right spot.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [May 28, 2021, 1:46am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/7 "2021-05-28T01:46:08Z")

</div>

> <https://github.com/dfinity/agent-rs/pull/195>
>
> This is a first pass at inferring when to make an update call instead of a query… call based on HTTP request methods.
> 
> It's based on \[this discussion thread\](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303?u=paulyoung) in the developer forum. Thanks to @nomeata for some feedback and help getting to this point.
> 
> I think this could be made a lot more configurable (perhaps via a file that is read when \`icx-proxy\` starts which maps methods/routes to functions) but what's here suits my needs for now so I thought I'd share it in case there's any interest in merging.
> 
> Thanks in advance for considering this change.
> 
> \*\*\*
> 
> \`\`\`typescript
> import Text "mo:base/Text";
> 
> actor {
> type HeaderField = (Text, Text);
> 
> type Token = {};
> 
> type StreamingCallbackHttpResponse = {
> body : Blob;
> token : Token;
> };
> 
> type StreamingStrategy = {
> #Callback : {
> callback : shared Token -\> async StreamingCallbackHttpResponse;
> token : Token;
> };
> };
> 
> type HttpRequest = {
> method : Text;
> url : Text;
> headers : \[HeaderField\];
> body : Blob;
> };
> 
> type HttpResponse = {
> status\_code : Nat16;
> headers : \[HeaderField\];
> body : Blob;
> streaming\_strategy : ?StreamingStrategy;
> };
> 
> public query func http\_request(request : HttpRequest) : async HttpResponse {
> {
> status\_code = 200;
> headers = \[\];
> body = Text.encodeUtf8("Response to " # request.method # " request (query)");
> streaming\_strategy = null;
> };
> };
> 
> public shared func http\_request\_update(request : HttpRequest) : async HttpResponse {
> {
> status\_code = 200;
> headers = \[\];
> body = Text.encodeUtf8("Response to " # request.method # " request (update)");
> streaming\_strategy = null;
> };
> };
> };
> \`\`\`
> 
> \`\`\`
> $ icx-proxy --fetch-root-key
> version: 0.2.1
> May 27 18:24:15.771 INFO Log Level: INFO
> May 27 18:24:15.797 INFO Starting server. Listening on http://127.0.0.1:3000/
> \`\`\`
> 
> \`\`\`
> $ curl -v -X GET -H "Content-type: application/json" -H "Accept: application/json" -d '{"method":"GET","url":"","headers":\[{"text":""}\],"body":null}' 'http://localhost:3000?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai'
> \* Trying 127.0.0.1...
> \* TCP\_NODELAY set
> \* Connected to localhost (127.0.0.1) port 3000 (#0)
> \> GET /?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai HTTP/1.1
> \> Host: localhost:3000
> \> User-Agent: curl/7.64.1
> \> Content-type: application/json
> \> Accept: application/json
> \> Content-Length: 61
> \>
> \* upload completely sent off: 61 out of 61 bytes
> \< HTTP/1.1 200 OK
> \< content-length: 31
> \< date: Fri, 28 May 2021 01:27:24 GMT
> \<
> \* Connection #0 to host localhost left intact
> Response to GET request (query)\* Closing connection 0
> \`\`\`
> 
> \`\`\`
> $ curl -v -X POST -H "Content-type: application/json" -H "Accept: application/json" -d '{"method":"GET","url":"","headers":\[{"text":""}\],"body":null}' 'http://localhost:3000?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai'
> Note: Unnecessary use of -X or --request, POST is already inferred.
> \* Trying 127.0.0.1...
> \* TCP\_NODELAY set
> \* Connected to localhost (127.0.0.1) port 3000 (#0)
> \> POST /?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai HTTP/1.1
> \> Host: localhost:3000
> \> User-Agent: curl/7.64.1
> \> Content-type: application/json
> \> Accept: application/json
> \> Content-Length: 61
> \>
> \* upload completely sent off: 61 out of 61 bytes
> \< HTTP/1.1 200 OK
> \< content-length: 33
> \< date: Fri, 28 May 2021 01:27:41 GMT
> \<
> \* Connection #0 to host localhost left intact
> Response to POST request (update)\* Closing connection 0
> \`\`\`

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [December 28, 2021, 9:18am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/8 "2021-12-28T09:18:16Z")

</div>

My first PR was closed because `icx-proxy` moved to its own repo.

The most relevant PR now is:

> <https://github.com/dfinity/icx-proxy/pull/6>
>
> This applies changes from https://github.com/dfinity/agent-rs/pull/195 that are …specific to \`icx-proxy\`.
> 
> It necessarily depends on a newer version of ~\`agent-rs\`~ \`ic-agent\` and \`ic-utils\`. This will most likely be something like \`10.X.0\` but temporarily uses a Git URL for now.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [January 11, 2022, 2:23am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/9 "2022-01-11T02:23:55Z")

</div>

The above PR was merged today 🙂

---

<div class="post-metadata">

**Author:** ![diegop](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/diegop/32/569_2.png) [@diegop](https://forum.dfinity.org/u/diegop)\
**Post date:** [January 11, 2022, 2:44am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/10 "2022-01-11T02:44:50Z")

</div>

Hallelujah! It is merged! Yay!

---

<div class="post-metadata">

**Author:** ![skilesare](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/skilesare/32/5609_2.png) [@skilesare](https://forum.dfinity.org/u/skilesare)\
**Post date:** [January 11, 2022, 4:15pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/11 "2022-01-11T16:15:28Z")

</div>

I’m trying to better understand what this PR does. Will this allow me to send POST/PUT method calls to the IC via HTTP and have them converted into update calls that go to http\_request\_update? Or is that still a ways off?

Am I correct in saying that http\_request only supports GET requests at the moment? Or it handles everything, but if you try to update something it will fail because http\_request interface endpoint is a query?

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [January 11, 2022, 4:49pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/12 "2022-01-11T16:49:51Z")

</div>

Canisters can handle HTTP requests by providing a `http_request` function. However, `http_request` only allows making `query` calls.

With my PR, canisters can now also provide a function called `http_request_update` that allows making `update` calls.

When handling a HTTP request inside of `http_request`, if it’s necessary to make an `update` call, `http_request` can now return a response including the field `upgrade` with a value of `true`. This results in `http_request_update` to be called instead.

Whether any of this happens due to HTTP methods like `GET` or `POST` (or other aspects of the request) is left entirely up to the canister. I had originally inferred whether to “upgrade” from `query` call to `update` based on the HTTP method but allowing the canister to determine that explicitly is more flexible.

---

<div class="post-metadata">

**Author:** ![nomeata](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/nomeata/32/733_2.png) [@nomeata](https://forum.dfinity.org/u/nomeata)\
**Post date:** [January 11, 2022, 10:33pm UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/13 "2022-01-11T22:33:29Z")

</div>

Is this live already? If not, what is the ETA? I’m eager to migrate my telegram bot to this interface and disable my own AWS-Bounday-Node (which had this feature for a year now… ;-))

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [January 12, 2022, 4:25am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/14 "2022-01-12T04:25:40Z")

</div>

@Daniel-Bloom might know.

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [January 24, 2022, 3:25am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/15 "2022-01-24T03:25:47Z")

</div>

@diegop do you know anything?

---

<div class="post-metadata">

**Author:** ![diegop](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/diegop/32/569_2.png) [@diegop](https://forum.dfinity.org/u/diegop)\
**Post date:** [January 24, 2022, 3:26am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/16 "2022-01-24T03:26:48Z")

</div>

No, I’ll ask around.

---

<div class="post-metadata">

**Author:** ![faraz.shaikh](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/faraz.shaikh/32/4005_2.png) [@faraz.shaikh](https://forum.dfinity.org/u/faraz.shaikh)\
**Post date:** [January 24, 2022, 5:20am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/17 "2022-01-24T05:20:24Z")

</div>

I am fairly certain this hasn’t been rolled out. I checked the update logs and I know for sure about an unrelated issue blocking production upgrades.

I will pull the built binary to ic stop gap repo. & update this thread when prod is up. (This week)

---

<div class="post-metadata">

**Author:** ![heyuanxun](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/heyuanxun/32/4695_2.png) [@heyuanxun](https://forum.dfinity.org/u/heyuanxun)\
**Post date:** [February 11, 2022, 7:44am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/18 "2022-02-11T07:44:05Z")

</div>

I use this code([feat: upgrade HTTP request calls from query to update upon canister's request by paulyoung · Pull Request #195 · dfinity/agent-rs · GitHub](https://github.com/dfinity/agent-rs/pull/195) ) and icx-proxy ([GitHub - dfinity/icx-proxy: A rust-based command line tool to serve as a gateway for a Internet Computer replica.](https://github.com/dfinity/icx-proxy)) to test at local environment.  
i try $curl -v -X POST -H “Content-type: application/json” -H “Accept: application/json” -d ‘{}’ ‘[http://localhost:8000?canisterId=ai7t5-aibaq-aaaaa-aaaaa-c](http://localhost:8000?canisterId=ai7t5-aibaq-aaaaa-aaaaa-c)’

But it return : Response to POST request (query)

would you tell where i get worng

---

<div class="post-metadata">

**Author:** ![paulyoung](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/paulyoung/32/5251_2.png) [@paulyoung](https://forum.dfinity.org/u/paulyoung)\
**Post date:** [February 12, 2022, 1:24am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/19 "2022-02-12T01:24:25Z")

</div>

That code at the top of the PR is out of date.

Basically, if `http_request` returns `upgrade: true` then `http_request_update` is called.

---

<div class="post-metadata">

**Author:** ![heyuanxun](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/heyuanxun/32/4695_2.png) [@heyuanxun](https://forum.dfinity.org/u/heyuanxun)\
**Post date:** [February 12, 2022, 7:28am UTC](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303/20 "2022-02-12T07:28:55Z")

</div>

i just wanna know why your [code](https://github.com/dfinity/agent-rs/pull/195) can return Response to POST request ( update)  
but i use you code at my computer return Response to POST request (query)

[Next page](https://forum.dfinity.org/t/feature-request-map-appropriate-http-request-methods-to-update-calls/4303.md?page=2)
