lambda_extension/
requests.rs1use crate::{Error, LogBuffering};
2use http::{Method, Request};
3use lambda_runtime_api_client::{body::Body, build_request};
4use serde::Serialize;
5
6const EXTENSION_NAME_HEADER: &str = "Lambda-Extension-Name";
7pub(crate) const EXTENSION_ID_HEADER: &str = "Lambda-Extension-Identifier";
8const EXTENSION_ERROR_TYPE_HEADER: &str = "Lambda-Extension-Function-Error-Type";
9const CONTENT_TYPE_HEADER_NAME: &str = "Content-Type";
10const CONTENT_TYPE_HEADER_VALUE: &str = "application/json";
11
12const EXTENSION_ACCEPT_FEATURE: &str = "Lambda-Extension-Accept-Feature";
15const EXTENSION_ACCEPT_FEATURE_VALUE: &str = "accountId";
16
17pub(crate) fn next_event_request(extension_id: &str) -> Result<Request<Body>, Error> {
18 let req = build_request()
19 .method(Method::GET)
20 .header(EXTENSION_ID_HEADER, extension_id)
21 .uri("/2020-01-01/extension/event/next")
22 .body(Body::empty())?;
23 Ok(req)
24}
25
26pub(crate) fn register_request(extension_name: &str, events: &[&str]) -> Result<Request<Body>, Error> {
27 let events = serde_json::json!({ "events": events });
28
29 let req = build_request()
30 .method(Method::POST)
31 .uri("/2020-01-01/extension/register")
32 .header(EXTENSION_NAME_HEADER, extension_name)
33 .header(EXTENSION_ACCEPT_FEATURE, EXTENSION_ACCEPT_FEATURE_VALUE)
34 .header(CONTENT_TYPE_HEADER_NAME, CONTENT_TYPE_HEADER_VALUE)
35 .body(Body::from(serde_json::to_string(&events)?))?;
36
37 Ok(req)
38}
39
40pub(crate) enum Api {
41 LogsApi,
42 TelemetryApi,
43}
44
45impl Api {
46 pub(crate) fn schema_version(&self) -> &str {
47 match *self {
48 Api::LogsApi => "2021-03-18",
49 Api::TelemetryApi => "2022-07-01",
50 }
51 }
52
53 pub(crate) fn uri(&self) -> &str {
54 match *self {
55 Api::LogsApi => "/2020-08-15/logs",
56 Api::TelemetryApi => "/2022-07-01/telemetry",
57 }
58 }
59}
60
61pub(crate) fn subscribe_request(
62 api: Api,
63 extension_id: &str,
64 types: Option<&[&str]>,
65 buffering: Option<LogBuffering>,
66 port_number: u16,
67) -> Result<Request<Body>, Error> {
68 let types = types.unwrap_or(&["platform", "function"]);
69
70 let data = serde_json::json!({
71 "schemaVersion": api.schema_version(),
72 "types": types,
73 "buffering": buffering.unwrap_or_default(),
74 "destination": {
75 "protocol": "HTTP",
76 "URI": format!("http://sandbox.localdomain:{port_number}"),
77 }
78 });
79
80 let req = build_request()
81 .method(Method::PUT)
82 .uri(api.uri())
83 .header(EXTENSION_ID_HEADER, extension_id)
84 .header(CONTENT_TYPE_HEADER_NAME, CONTENT_TYPE_HEADER_VALUE)
85 .body(Body::from(serde_json::to_string(&data)?))?;
86
87 Ok(req)
88}
89
90#[derive(Debug, Serialize)]
92#[serde(rename_all = "camelCase")]
93pub struct ErrorRequest<'a> {
94 pub error_message: &'a str,
96 pub error_type: &'a str,
98 pub stack_trace: Vec<&'a str>,
100}
101
102pub fn init_error(
104 extension_id: &str,
105 error_type: &str,
106 request: Option<ErrorRequest<'_>>,
107) -> Result<Request<Body>, Error> {
108 error_request("init", extension_id, error_type, request)
109}
110
111pub fn exit_error(
113 extension_id: &str,
114 error_type: &str,
115 request: Option<ErrorRequest<'_>>,
116) -> Result<Request<Body>, Error> {
117 error_request("exit", extension_id, error_type, request)
118}
119
120fn error_request(
121 error_type: &str,
122 extension_id: &str,
123 error_str: &str,
124 request: Option<ErrorRequest<'_>>,
125) -> Result<Request<Body>, Error> {
126 let uri = format!("/2020-01-01/extension/{error_type}/error");
127
128 let body = match request {
129 None => Body::empty(),
130 Some(err) => Body::from(serde_json::to_string(&err)?),
131 };
132
133 let req = build_request()
134 .method(Method::POST)
135 .uri(uri)
136 .header(EXTENSION_ID_HEADER, extension_id)
137 .header(EXTENSION_ERROR_TYPE_HEADER, error_str)
138 .body(body)?;
139 Ok(req)
140}