Proper example of handling HTTP GET request in Rust

I’m a newcomer and I’m lost in examples, can’t find proper.

I’d like a canister to handle HTTP requests. I see it should implement http_request. I defined did as follows:

type header = record {
  name : text;
  value : text;
};
type request = record {
  method : text;
  url : text;
  headers : vec header;
  body : blob;
};
type response = record {
  status_code : nat16;
  headers : vec header;
  body : blob;
};
service : {
  http_request : (request) -> (response);
}

Then Rust implementation:

#[derive(CandidType, Deserialize)]
pub struct HeaderField {
    pub name: String,
    pub value: String,
}

#[derive(CandidType, Deserialize)]
pub struct HttpRequest {
    pub method: String,
    pub url: String,
    pub headers: Vec<HeaderField>,
    pub body: Vec<u8>,
}

#[derive(CandidType)]
pub struct HttpResponse {
    pub status_code: u16,
    pub headers: Vec<HeaderField>,
    pub body: Vec<u8>,
}

I deploy it to ic. It returns the canister ID: 3sanc-...-cai. Then I try to curl it with: curl -X GET "https://3sanc-...-cai.raw.icp0.io/query". It fails with the error:

Replica Error: reject code CanisterError, message IC0503: Error from Canister 3sanc-...-cai: Canister called `ic0.trap` with message: failed to decode call arguments: Custom(Fail to decode argument 0 from table0 to record {
  url : text;
  method : text;
  body : blob;
  headers : vec record { value : text; name : text };
}

Caused by:
    Subtyping error: text).
Consider gracefully handling failures from this canister or altering the canister to handle exceptions. See documentation: http://internetcomputer.org/docs/current/references/execution-errors#trapped-explicitly, error code Some("IC0503")

And I have no idea where it errors with text subtyping. Any suggestions what’s the problem and how to fix it?

From the spec:

type HeaderField = record { text; text; };

but you define

headers : vec record { value : text; name : text };

If you use a tuple instead of a struct it should work:

pub type HeaderField = (String, String);
1 Like