Http outcall stopped

Why suddenly HttpOutCall not working, what happened?

Here is the error:
Call failed:
Canister: xqsqi-eimaa-aaaxi-q3kxa-cai
Method: getData(update)
“Request ID”: “2a45904a2600a10a888d8f7c74b4685ba45c0e6327a84d5889625865285db949”
“Error code”: “IC0406”
“Reject code”: “4”
“Reject message”: “Connecting to icptest-111.europe-west1.run.app failed: Failed to directly connect: hyper_util::client::legacy::Error(SendRequest, hyper::Error(Http2, Error { kind: Reset(StreamId(1), PROTOCOL_ERROR, Remote) }))”

Can you share the whole request? We suspect it’s because of the headers you send

let request_headers = [
  { name = "Host"; value = host # ":443" },
  { name = "User-Agent"; value = "icp_google_agent" },
  { name = "Content-Type"; value = "application/json" },
  { name = "Idempotency-Key"; value = idempotency_key },
  { name = "accept"; value = "text/plain" },
  {
    name = apiEndpointSettings.api_key; 
    value = apiEndpointSettings.api_key_value; 
  }
];

It always worked

  func _processRequest(idempotency_key : Text, body : Text, resource : Text, verb : HttpOutCallVerb) : async Text {
    let ic : OutcallsTypes.IC = actor ("aaaaa-aa");
    let host : Text = apiEndpointSettings.host;
    let url = apiEndpointSettings.url # resource;
    let request_headers = [
      { name = "Host"; value = host # ":443" },
      { name = "User-Agent"; value = "icp_google_agent" },
      { name = "Content-Type"; value = "application/json" },
      { name = "Idempotency-Key"; value = idempotency_key },
      { name = "accept"; value = "text/plain" },
      {
        name = apiEndpointSettings.api_key; 
        value = apiEndpointSettings.api_key_value; 
      },
    ];

    let request_body_as_Blob : Blob = Text.encodeUtf8(body);
    let request_body_as_nat8 : [Nat8] = Blob.toArray(request_body_as_Blob);

    let transform_context : OutcallsTypes.TransformContext = {
      function = transform;
      context = Blob.fromArray([]);
    };

    let max_response_bytes_nat : Nat = 2000000;
    let max_response_bytes_nat64 : ?Nat64 = ?(Nat64.fromNat(max_response_bytes_nat));

    let http_request : OutcallsTypes.HttpRequestArgs = {
      url = url;
      max_response_bytes = max_response_bytes_nat64; //optional for request
      headers = request_headers;
      body = ?request_body_as_nat8;
      method = verb;
      transform = ?transform_context;
    };

    Cycles.add(apiEndpointSettings.call_cycles);

    let http_response : OutcallsTypes.HttpResponsePayload = await ic.http_request(http_request);
    let response_body : Blob = Blob.fromArray(http_response.body);
    let status_code : Nat = http_response.status;
    let decoded_text : Text = switch (Text.decodeUtf8(response_body)) {
      case (null) { "Error: Unable to decode response. Status code: " # Nat.toText(status_code) };
      case (?y) { "Status code: " # Nat.toText(status_code) # ", Body: " # y };
    };
    return decoded_text;

  };

  public query func transform(raw : OutcallsTypes.TransformArgs) : async OutcallsTypes.CanisterHttpResponsePayload {
    let transformed : OutcallsTypes.CanisterHttpResponsePayload = {
      status = raw.response.status;
      body = raw.response.body;
      headers = [
        {
          name = "Content-Security-Policy";
          value = "default-src 'self'";
        },
        {
          name = "Referrer-Policy";
          value = "strict-origin";
        },
        {
          name = "Permissions-Policy";
          value = "geolocation=(self)";
        },
        {
          name = "Strict-Transport-Security";
          value = "max-age=63072000";
        },
        {
          name = "X-Frame-Options";
          value = "DENY";
        },
        {
          name = "X-Content-Type-Options";
          value = "nosniff";
        },
      ];
    };
    transformed;
  };

There was a recent change in the HTTPS Outcall feature to support HTTP/2.
We didn’t anticipate this to be a breaking change, but it turned out that HTTP/2 doesn’t support setting the Host header in the request.

Please try to remove the following line, then the outcall should work again.

4 Likes

Problem is solved now, thanks for your time!

    let request_headers = [
      { name = "authority"; value = host},
      { name = "path"; value = resource},
      { name = "scheme"; value = "https" },
      { name = "User-Agent"; value = "agent007" },
      { name = "Content-Type"; value = "application/json" },
      { name = "Idempotency-Key"; value = idempotency_key },
      { name = "accept"; value = "text/plain" },
      {
        name = settings.api_key; 
        value = settings.api_key_value; 
      },
    ];
1 Like