Http_request decode failure

Hitting the http_request canister_query WASM endpoint using dfx canister call http_request successfully returns:

(
  record {
    status = 200 : nat;
    body = blob "\5c1f\5c8b\5c08\5c00\5c4d\5c89\5c24\5c66\5c02\5cff\5cb3\5cc9\5c28\5cc9\5ccd\5cb1\5cb3\5c49\5cca\5c4f\5ca9\5cb4\5cf3\5c48\5ccd\5cc9\5cc9\5cd7\5c51\5c08\5ccf\5c2f\5cca\5c49\5c51\5cb4\5cd1\5c07\5c8b\5cd9\5ce8\5c83\5c15\5c00\5c00\5cc3\5ca2\5c64\5ccd\5c27\5c00\5c00\5c00";
    headers = vec { record { value = "Content-Type"; name = "gzip" } };
  },
)

However, trying to use the backend UI for the canister on the mainnet to do the same thing gives me:

Server returned an error:
Code: 400 ()
Body: unable_to_parse_http_arg: unable to decode arg as HttpRequest: Fail to decode argument 0 from table11 to record {
url : text;
method : text;
body : vec nat8;
headers : vec record { text; text };
}

Any idea where this error is originating from? Given that it’s about the request parameters, it seems like it’s before the http_request function is actually hit, and I’m not doing anything to attempt to parse the request args anyway within the WASM.

1 Like

It sounds like the Candid UI is sending down incorrect arguments for the http_request parameters. Do you have screenshots of exactly what you are putting into the Candid UI?

Using canister call with dfx gives the same error:

dfx canister call ic_canister http_request "( record { url = \"index.html\"; method = variant { get }; max_response_bytes = null; body = null; transform = null; headers = vec { record { value = \"Accept-Encoding\"; name = \"gzip\" }; }; }, )"

Error:

The replica returned an HTTP Error: Http Error: status 400 Bad Request, content type "text/plain; charset=utf-8", content: unable_to_parse_http_arg: unable to decode arg as HttpRequest: Fail to decode argument 0 from table0 to record {
  url : text;
  method : text;
  body : vec nat8;
  headers : vec record { text; text };
}

While running it locally succeeds. Here’s a formatted version of the requests:

(
  record {
    url = "index.html";
    method = variant { get };
    max_response_bytes = null;
    body = null;
    transform = null;
    headers = vec {
      record { value = "Accept-Encoding"; name = "gzip" };
    };
  },
)

Also I’m generating the input using the didc random utility, so I would expect the format to be correct.

The canister you are calling does not support the same candid interface that you’re using. It’s trying to decode your request into this:

record {
  url : text;
  method : text;
  body : vec nat8;
  headers : vec record { text; text };
}

But you are sending this:

record {
  url = \"index.html\";
  method = variant { get };
  max_response_bytes = null;
  body = null;
  transform = null;
  headers = vec {
    record {
      value = \"Accept-Encoding\";
      name = \"gzip\" 
    };
  };
}

There’s multiple mismatches between what you’re sending and what the canister expects:

  • method is text, not a variant
  • max_response_bytes and transform don’t exist
  • headers is vec record { text; text; } not vec record { value: text; name: text }

If it’s working locally, but not on mainnet then it looks like you have an different version of your canister deployed to mainnet than what you have locally.

If making a DFX call works, but Candid UI doesn’t work, then there’s probably a mismatch between your Candid definition and what you have in your canister.

On another note, what’s your intention with using http_request? If this is intended to be used with the HTTP Gateway then you need to stick to Candid interface that’s in the spec, otherwise it won’t work.

If you’re not intending to use the HTTP Gateway then I’d encourage renaming your method to not confuse with the standardized http_request endpoint.

Aha, you’re right. I think I had taken the http_request signature from the management canister because I was searching for “http_request” instead of “HttpRequest”, and ended up in the wrong docs.

I was able to sort it out after switching to the correct signatures. Granted, I’m not really sure why it was trying to decode that signature because it was reflecting my incorrect signature in the UI. Maybe something in the chain knew http_request was a system endpoint so it was using the expected signature.

Appreciate the help!