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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
use std::fmt;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use crate::oracle::OracleValue;
type HeadersInnerType = std::collections::BTreeMap<String, OracleValue>;
/// A structure representing the headers of an HTTP request.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
pub struct Headers(HeadersInnerType);
#[derive(Error, Debug)]
pub enum HeadersError {
#[error("Failed to decode {encoding} for parameter '{param}': {reason}")]
DecodeError {
param: String,
encoding: String,
reason: String,
},
#[error("JSON parsing error: {reason}")]
JsonError { reason: String },
}
impl Headers {
/// Creates a new Headers instance from the provided HeadersType map.
///
/// # Arguments
/// * `headers` - A HeadersInnerType containing header key-value pairs
///
/// # Returns
/// A new Headers instance wrapping the provided map
pub fn new(headers: HeadersInnerType) -> Self {
Headers(headers)
}
/// Inserts a plain text header value into the headers map.
///
/// This method adds a header with a plain (unencrypted) value to the headers collection.
///
/// # Arguments
/// * `key` - The header name
/// * `value` - The plain text header value
pub fn insert_plain(&mut self, key: String, value: String) {
self.0.insert(key, OracleValue::Plain(value));
}
/// Inserts an encrypted header value into the headers map.
///
/// This method adds a header with an encrypted value to the headers collection.
/// The encrypted value should be base64-encoded ciphertext that can be decrypted
/// within the TEE using the stored secret key.
///
/// # Arguments
/// * `key` - The header name
/// * `encrypted_value` - The base64-encoded encrypted header value
pub fn insert_encrypted(&mut self, key: String, encrypted_value: String) {
self.0.insert(key, OracleValue::Encrypted(encrypted_value));
}
/// Provide a public accessor to move out the inner map.
/// This enables other crates to consume the headers safely.
///
/// # Returns
/// The inner HeadersInnerType map, consuming the Headers instance
pub fn into_inner(self) -> HeadersInnerType {
self.0
}
/// Parses base64-encoded headers string into a Headers instance.
///
/// This method decodes a base64-encoded string containing JSON headers data
/// and deserializes it into a Headers structure.
///
/// # Arguments
/// * `headers_b64` - Base64-encoded string containing JSON headers
///
/// # Returns
/// * `Ok(Headers)` - Successfully parsed headers
/// * `Err(HeadersError)` - If base64 decoding, UTF-8 conversion, or JSON parsing fails
#[cfg(feature = "non-pdk")]
pub fn parse_b64(headers_b64: &str) -> Result<Self, HeadersError> {
use fastcrypto::{encoding, encoding::Encoding};
let headers_bytes =
encoding::Base64::decode(headers_b64).map_err(|err| HeadersError::DecodeError {
param: "headers".to_string(),
encoding: "base64".to_string(),
reason: err.to_string(),
})?;
let headers_str =
std::str::from_utf8(&headers_bytes).map_err(|err| HeadersError::DecodeError {
param: "headers".to_string(),
encoding: "utf-8".to_string(),
reason: err.to_string(),
})?;
let parsed_headers: Headers =
serde_json::from_str(headers_str).map_err(|error| HeadersError::JsonError {
reason: format!("Invalid headers JSON: {error}"),
})?;
Ok(parsed_headers)
}
}
impl std::str::FromStr for Headers {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let headers: HeadersInnerType = serde_json::from_str(s).map_err(|e| e.to_string())?;
Ok(Headers(headers))
}
}
impl fmt::Display for Headers {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", serde_json::to_string(&self.0).unwrap())
}
}