Skip to main content

netlog/
http.rs

1// Copyright (C) 2025, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use std::collections::BTreeMap;
28
29use serde::Deserialize;
30
31use super::EventHeader;
32use super::SourceDependency;
33
34#[derive(Debug)]
35pub enum Event {
36    HttpTransactionSendRequestHeaders(HttpTransactionSendRequestHeadersEvent),
37    HttpTransactionHttp2SendRequestHeaders(
38        HttpTransactionHttp2SendRequestHeadersEvent,
39    ),
40    HttpTransactionQuicSendRequestHeaders(
41        HttpTransactionQuicSendRequestHeadersEvent,
42    ),
43    HttpTransactionReadResponseHeaders(HttpTransactionReadResponseHeadersEvent),
44    HttpStreamJobBoundToRequest(HttpStreamJobBoundToRequestEvent),
45    HttpStreamRequestBoundToJob(HttpStreamRequestBoundToJobEvent),
46    HttpStreamRequestBoundToQuicSession(HttpStreamRequestBoundToQuicSessionEvent),
47}
48#[derive(Deserialize, Debug, Default)]
49pub struct HttpTransactionSendRequestHeadersParams {
50    pub headers: Vec<String>,
51}
52
53#[derive(Deserialize, Debug, Default)]
54pub struct HttpTransactionSendRequestHeadersEvent {
55    pub params: HttpTransactionSendRequestHeadersParams,
56}
57
58#[derive(Deserialize, Debug, Default)]
59pub struct HttpTransactionHttp2SendRequestHeadersParams {
60    pub headers: Vec<String>,
61}
62
63#[derive(Deserialize, Debug, Default)]
64pub struct HttpTransactionHttp2SendRequestHeadersEvent {
65    pub params: HttpTransactionHttp2SendRequestHeadersParams,
66}
67
68#[derive(Deserialize, Debug, Default)]
69pub struct HttpTransactionQuicSendRequestHeadersParams {
70    pub headers: Vec<String>,
71    pub quic_priority_incremental: bool,
72    pub quic_priority_type: String,
73    pub quic_priority_urgency: u8,
74    pub quic_stream_id: u64,
75}
76
77#[derive(Deserialize, Debug, Default)]
78pub struct HttpTransactionQuicSendRequestHeadersEvent {
79    pub params: HttpTransactionQuicSendRequestHeadersParams,
80}
81
82#[derive(Deserialize, Debug, Default)]
83pub struct HttpTransactionReadResponseHeadersParams {
84    pub headers: Vec<String>,
85}
86
87#[derive(Deserialize, Debug, Default)]
88pub struct HttpTransactionReadResponseHeadersEvent {
89    pub params: HttpTransactionReadResponseHeadersParams,
90}
91
92#[derive(Deserialize, Debug, Default)]
93pub struct HttpStreamJobBoundToRequestParams {
94    pub source_dependency: SourceDependency,
95}
96
97#[derive(Deserialize, Debug, Default)]
98pub struct HttpStreamRequestBoundToJobEvent {
99    pub params: HttpStreamJobBoundToRequestParams,
100}
101
102#[derive(Deserialize, Debug, Default)]
103pub struct HttpStreamRequestBoundToJobParams {
104    pub source_dependency: SourceDependency,
105}
106
107#[derive(Deserialize, Debug, Default)]
108pub struct HttpStreamJobBoundToRequestEvent {
109    pub params: HttpStreamJobBoundToRequestParams,
110}
111
112#[derive(Deserialize, Debug, Default)]
113pub struct HttpStreamRequestBoundToQuicSessionEvent {
114    pub params: HttpStreamRequestBoundToQuicSessionParams,
115}
116
117#[derive(Deserialize, Debug, Default)]
118pub struct HttpStreamRequestBoundToQuicSessionParams {
119    pub source_dependency: SourceDependency,
120}
121
122pub fn headers_to_map(hdrs: &[String]) -> BTreeMap<String, String> {
123    let mut ret = BTreeMap::new();
124
125    for hdr in hdrs {
126        let mut split = hdr.split(": ");
127        let name = split.next();
128        let val = split.next();
129
130        match (name, val) {
131            (Some(k), Some(v)) => {
132                ret.insert(k.to_string(), v.to_string());
133            },
134
135            (Some(k), None) => {
136                ret.insert(k.to_string(), "".to_string());
137            },
138
139            _ => (),
140        }
141    }
142
143    ret
144}
145
146/// Parses the provided `event` based on the event type provided in `event_hdr`.
147pub fn parse_event(
148    event_hdr: &EventHeader, event: &[u8],
149) -> Option<super::Event> {
150    match event_hdr.ty_string.as_str() {
151        "HTTP_TRANSACTION_HTTP2_SEND_REQUEST_HEADERS" => {
152            let ev: HttpTransactionHttp2SendRequestHeadersEvent =
153                serde_json::from_slice(event).unwrap();
154            return Some(super::Event::Http(
155                Event::HttpTransactionHttp2SendRequestHeaders(ev),
156            ));
157        },
158
159        "HTTP_TRANSACTION_QUIC_SEND_REQUEST_HEADERS" => {
160            let ev: HttpTransactionQuicSendRequestHeadersEvent =
161                serde_json::from_slice(event).unwrap();
162            return Some(super::Event::Http(
163                Event::HttpTransactionQuicSendRequestHeaders(ev),
164            ));
165        },
166
167        "HTTP_TRANSACTION_SEND_REQUEST_HEADERS" => {
168            let ev: HttpTransactionSendRequestHeadersEvent =
169                serde_json::from_slice(event).unwrap();
170            return Some(super::Event::Http(
171                Event::HttpTransactionSendRequestHeaders(ev),
172            ));
173        },
174
175        "HTTP_TRANSACTION_READ_RESPONSE_HEADERS" => {
176            let ev: HttpTransactionReadResponseHeadersEvent =
177                serde_json::from_slice(event).unwrap();
178            return Some(super::Event::Http(
179                Event::HttpTransactionReadResponseHeaders(ev),
180            ));
181        },
182
183        "HTTP_STREAM_REQUEST_BOUND_TO_JOB" => {
184            let ev: HttpStreamRequestBoundToJobEvent =
185                serde_json::from_slice(event).unwrap();
186            return Some(super::Event::Http(Event::HttpStreamRequestBoundToJob(
187                ev,
188            )));
189        },
190
191        "HTTP_STREAM_JOB_BOUND_TO_REQUEST" => {
192            let ev: HttpStreamJobBoundToRequestEvent =
193                serde_json::from_slice(event).unwrap();
194            return Some(super::Event::Http(Event::HttpStreamJobBoundToRequest(
195                ev,
196            )));
197        },
198
199        "HTTP_STREAM_REQUEST_BOUND_TO_QUIC_SESSION" => {
200            let ev: HttpStreamRequestBoundToQuicSessionEvent =
201                serde_json::from_slice(event).unwrap();
202            return Some(super::Event::Http(
203                Event::HttpStreamRequestBoundToQuicSession(ev),
204            ));
205        },
206
207        // ignore these for now
208        "HTTP_TRANSACTION_READ_EARLY_HINTS_RESPONSE_HEADERS" |
209        "HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS" |
210        "HTTP_TRANSACTION_RESTART_AFTER_ERROR" |
211        "HTTP_TRANSACTION_RESTART_MISDIRECTED_REQUEST" |
212        "HTTP_TRANSACTION_SEND_REQUEST_BODY" |
213        "HTTP_TRANSACTION_SEND_TUNNEL_HEADERS" |
214        "HTTP_TRANSACTION_TUNNEL_READ_HEADERS" |
215        "HTTP_TRANSACTION_TUNNEL_SEND_REQUEST" => (),
216
217        // ignore these ones since they contain no extra params
218        "HTTP_TRANSACTION_SEND_REQUEST" |
219        "HTTP_TRANSACTION_READ_HEADERS" |
220        "HTTP_TRANSACTION_READ_BODY" => (),
221
222        _ => log::trace!("skipping unknown type....{}", event_hdr.ty_string),
223    }
224
225    None
226}