1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::;
use ;
use HashTree;
use Serialize;
/// Adds the [`IC-Certificate` header](https://internetcomputer.org/docs/references/http-gateway-protocol-spec/#the-certificate-header)
/// to a given [`HttpResponse`]. This header is used by the HTTP Gateway to verify the authenticity of query call responses made to the
/// `http_request` method of the target canister.
///
/// # Arguments
///
/// * `data_certificate` - A certificate used by the HTTP Gateway to verify a response.
/// Retrieved using `ic_cdk::api::data_certificate`. This value is not validated by this function
/// and is expected to be a valid certificate. The function will not fail if the certificate is invalid,
/// but verification of the certificate by the HTTP Gateway will fail.
/// * `response` - The [`HttpResponse`] to add the certificate header to.
/// Created using [`HttpResponse::builder()`](crate::HttpResponse::builder).
/// * `witness` - A pruned merkle tree revealing the relevant certification for the current response.
/// Created using [`HttpCertificationTree::witness()`](crate::HttpCertificationTree::witness).
/// The witness is not validated to be correct for the given response, and the function will not fail
/// if the witness is invalid. The HTTP Gateway will fail to verify the response if the witness is invalid.
/// * `expr_path` - An expression path for the current response informing the HTTP Gateway where the
/// relevant certification is present in the merkle tree. Created using
/// [`HttpCertificationPath::to_expr_path()`](crate::HttpCertificationPath::to_expr_path). The expression path
/// is not validated to be correct for the given response, and the function will not fail if the expression path is invalid.
///
/// # Examples
///
/// ```
/// use ic_http_certification::{HttpCertification, HttpRequest, HttpResponse, DefaultCelBuilder, DefaultResponseCertification, HttpCertificationTree, HttpCertificationTreeEntry, HttpCertificationPath, CERTIFICATE_EXPRESSION_HEADER_NAME, CERTIFICATE_HEADER_NAME, utils::add_v2_certificate_header};
///
/// let cel_expr = DefaultCelBuilder::full_certification().build();
///
/// let request = HttpRequest::get("/index.html?foo=a&bar=b&baz=c").build();
///
/// let mut response = HttpResponse::builder()
/// .with_headers(vec![(CERTIFICATE_EXPRESSION_HEADER_NAME.to_string(), cel_expr.to_string())])
/// .build();
///
/// let request_url = "/example.json";
/// let path = HttpCertificationPath::exact(request_url);
/// let expr_path = path.to_expr_path();
///
/// let certification = HttpCertification::full(&cel_expr, &request, &response, None).unwrap();
/// let entry = HttpCertificationTreeEntry::new(&path, &certification);
///
/// let mut http_certification_tree = HttpCertificationTree::default();
/// http_certification_tree.insert(&entry);
///
/// // this should normally be retrieved using `ic_cdk::api::data_certificate()`.
/// let data_certificate = vec![1, 2, 3];
///
/// let witness = http_certification_tree.witness(&entry, request_url).unwrap();
/// add_v2_certificate_header(
/// &data_certificate,
/// &mut response,
/// &witness,
/// &expr_path
/// );
///
/// assert_eq!(
/// response.headers(),
/// vec![
/// (CERTIFICATE_EXPRESSION_HEADER_NAME.to_string(), cel_expr.to_string()),
/// (
/// CERTIFICATE_HEADER_NAME.to_string(),
/// "certificate=:AQID:, tree=:2dn3gwJJaHR0cF9leHBygwJMZXhhbXBsZS5qc29ugwJDPCQ+gwJYIFJ2k+R/YYbgGPADidRdRwDurH06HXACVHlTIVrv1q4WgwJYIGvHTtoVXrGXb4aD1BvH+OW26d0CtLUdA43LP+42N6xpgwJYIM7zUx3VibIaHEUF14Kx813l3Xlilg43Y5uGaABAA/i9ggNA:, expr_path=:2dn3g2lodHRwX2V4cHJsZXhhbXBsZS5qc29uYzwkPg==:, version=2".to_string(),
/// ),
/// ]
/// );
/// ```