-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathhttp.rs
More file actions
147 lines (125 loc) · 4.51 KB
/
Copy pathhttp.rs
File metadata and controls
147 lines (125 loc) · 4.51 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
//! OCSF `http_request`, `http_response`, and `url` objects.
use serde::{Deserialize, Serialize};
use crate::enums::HttpMethod;
/// OCSF HTTP Request object.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HttpRequest {
/// HTTP method (e.g., "GET", "POST").
pub http_method: HttpMethod,
/// Request URL.
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<Url>,
}
/// OCSF HTTP Response object.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HttpResponse {
/// HTTP status code.
pub code: u16,
}
/// OCSF URL object.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Url {
/// URL scheme (e.g., "https").
#[serde(skip_serializing_if = "Option::is_none")]
pub scheme: Option<String>,
/// Hostname.
#[serde(skip_serializing_if = "Option::is_none")]
pub hostname: Option<String>,
/// URL path.
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
/// Port number.
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<u16>,
}
impl Url {
/// Create a URL from its components.
#[must_use]
pub fn new(scheme: &str, hostname: &str, path: &str, port: u16) -> Self {
Self {
scheme: Some(scheme.to_string()),
hostname: Some(hostname.to_string()),
path: Some(path.to_string()),
port: Some(port),
}
}
/// Format as a display string.
///
/// Includes the port when it is present and differs from the scheme default
/// (443 for `https`, 80 for `http`).
#[must_use]
pub fn to_display_string(&self) -> String {
let scheme = self.scheme.as_deref().unwrap_or("https");
let hostname = self.hostname.as_deref().unwrap_or("unknown");
let path = self.path.as_deref().unwrap_or("/");
let port_suffix = match self.port {
Some(443) if scheme == "https" => String::new(),
Some(80) if scheme == "http" => String::new(),
Some(p) => format!(":{p}"),
None => String::new(),
};
format!("{scheme}://{hostname}{port_suffix}{path}")
}
}
impl HttpRequest {
/// Create a new HTTP request.
#[must_use]
pub fn new(method: &str, url: Url) -> Self {
Self {
http_method: method.parse().unwrap(),
url: Some(url),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_http_request_serialization() {
let req = HttpRequest::new("GET", Url::new("https", "api.example.com", "/v1/data", 443));
let json = serde_json::to_value(&req).unwrap();
assert_eq!(json["http_method"], "GET");
assert_eq!(json["url"]["scheme"], "https");
assert_eq!(json["url"]["hostname"], "api.example.com");
assert_eq!(json["url"]["path"], "/v1/data");
assert_eq!(json["url"]["port"], 443);
}
#[test]
fn test_url_display_string_default_port() {
let url = Url::new("https", "api.example.com", "/v1/data", 443);
assert_eq!(url.to_display_string(), "https://api.example.com/v1/data");
let url = Url::new("http", "example.com", "/index", 80);
assert_eq!(url.to_display_string(), "http://example.com/index");
}
#[test]
fn test_url_display_string_non_default_port() {
let url = Url::new("http", "172.20.0.1", "/test", 9876);
assert_eq!(url.to_display_string(), "http://172.20.0.1:9876/test");
let url = Url::new("https", "api.example.com", "/v1/data", 8443);
assert_eq!(
url.to_display_string(),
"https://api.example.com:8443/v1/data"
);
// HTTP on 443 is non-default — should show port
let url = Url::new("http", "example.com", "/path", 443);
assert_eq!(url.to_display_string(), "http://example.com:443/path");
}
#[test]
fn test_url_display_string_no_port() {
let url = Url {
scheme: Some("https".to_string()),
hostname: Some("example.com".to_string()),
path: Some("/path".to_string()),
port: None,
};
assert_eq!(url.to_display_string(), "https://example.com/path");
}
#[test]
fn test_http_response() {
let resp = HttpResponse { code: 200 };
let json = serde_json::to_value(&resp).unwrap();
assert_eq!(json["code"], 200);
}
}